From 668bad61216cd1b4b01a003cda7f7665d165f92f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 4 Jun 2017 11:04:54 -0700 Subject: [PATCH 001/159] print success after reset assertions #1057 Signed-off-by: Nikolaj Bjorner --- src/cmd_context/basic_cmds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index 26cd0628e..a098f3c94 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -250,7 +250,7 @@ ATOMIC_CMD(get_assertions_cmd, "get-assertions", "retrieve asserted terms when i -ATOMIC_CMD(reset_assertions_cmd, "reset-assertions", "reset all asserted formulas (but retain definitions and declarations)", ctx.reset_assertions();); +ATOMIC_CMD(reset_assertions_cmd, "reset-assertions", "reset all asserted formulas (but retain definitions and declarations)", ctx.reset_assertions(); ctx.print_success();); UNARY_CMD(set_logic_cmd, "set-logic", "", "set the background logic.", CPK_SYMBOL, symbol const &, if (ctx.set_logic(arg)) From 4f04301305d1ce26476ce832ea6a51cb1f8730a5 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 5 Jun 2017 07:55:32 -0700 Subject: [PATCH 002/159] add documentation per #1058 Signed-off-by: Nikolaj Bjorner --- src/api/z3_api.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 45065f856..dec8f34dd 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -5349,6 +5349,9 @@ extern "C" { /** \brief Add a new formula \c a to the given goal. + Conjunctions are split into separate formulas. + If the formula \c a is \c true, then nothing is added. + If the formula \c a is \c false, then the entire goal is replaced by the formula \c false. def_API('Z3_goal_assert', VOID, (_in(CONTEXT), _in(GOAL), _in(AST))) */ From af285d02c3ccf7c3c7f3f75e18ae56ae1857d5db Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 5 Jun 2017 08:38:28 -0700 Subject: [PATCH 003/159] add documentation per #1058 Signed-off-by: Nikolaj Bjorner --- src/api/z3_api.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index dec8f34dd..93da0b2c7 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -5350,6 +5350,7 @@ extern "C" { /** \brief Add a new formula \c a to the given goal. Conjunctions are split into separate formulas. + If the goal is \c false, adding new formulas is a no-op. If the formula \c a is \c true, then nothing is added. If the formula \c a is \c false, then the entire goal is replaced by the formula \c false. From 83e9c40265ef66c771f673aca66f7eef1634102c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 6 Jun 2017 16:04:38 +0100 Subject: [PATCH 004/159] Added __deepcopy__ operators to ref-counted objects in the Python API --- src/api/python/z3/z3.py | 64 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/src/api/python/z3/z3.py b/src/api/python/z3/z3.py index b4cdf834b..b86e9a797 100644 --- a/src/api/python/z3/z3.py +++ b/src/api/python/z3/z3.py @@ -50,6 +50,7 @@ from fractions import Fraction import sys import io import math +import copy if sys.version < '3': def _is_int(v): @@ -288,6 +289,9 @@ class AstRef(Z3PPObject): if self.ctx.ref() is not None: Z3_dec_ref(self.ctx.ref(), self.as_ast()) + def __deepcopy__(self, memo={}): + return _to_ast_ref(self.ast, self.ctx) + def __str__(self): return obj_to_string(self) @@ -4355,6 +4359,11 @@ class Datatype: self.name = name self.constructors = [] + def __deepcopy__(self, memo={}): + r = Datatype(self.name, self.ctx) + r.constructors = copy.deepcopy(self.constructors) + return r + def declare_core(self, name, rec_name, *args): if __debug__: _z3_assert(isinstance(name, str), "String expected") @@ -4645,11 +4654,17 @@ class ParamsRef: Consider using the function `args2params` to create instances of this object. """ - def __init__(self, ctx=None): + def __init__(self, ctx=None, params=None): self.ctx = _get_ctx(ctx) - self.params = Z3_mk_params(self.ctx.ref()) + if params is None: + self.params = Z3_mk_params(self.ctx.ref()) + else: + self.params = params Z3_params_inc_ref(self.ctx.ref(), self.params) + def __deepcopy__(self, memo={}): + return ParamsRef(self.ctx, self.params) + def __del__(self): if self.ctx.ref() is not None: Z3_params_dec_ref(self.ctx.ref(), self.params) @@ -4709,6 +4724,9 @@ class ParamDescrsRef: self.descr = descr Z3_param_descrs_inc_ref(self.ctx.ref(), self.descr) + def __deepcopy__(self, memo={}): + return ParamsDescrsRef(self.descr, self.ctx) + def __del__(self): if self.ctx.ref() is not None: Z3_param_descrs_dec_ref(self.ctx.ref(), self.descr) @@ -4770,6 +4788,9 @@ class Goal(Z3PPObject): self.goal = Z3_mk_goal(self.ctx.ref(), models, unsat_cores, proofs) Z3_goal_inc_ref(self.ctx.ref(), self.goal) + def __deepcopy__(self, memo={}): + return Goal(False, False, False, self.ctx, self.goal) + def __del__(self): if self.goal is not None and self.ctx.ref() is not None: Z3_goal_dec_ref(self.ctx.ref(), self.goal) @@ -5032,6 +5053,9 @@ class AstVector(Z3PPObject): self.ctx = ctx Z3_ast_vector_inc_ref(self.ctx.ref(), self.vector) + def __deepcopy__(self, memo={}): + return AstVector(self.vector, self.ctx) + def __del__(self): if self.vector is not None and self.ctx.ref() is not None: Z3_ast_vector_dec_ref(self.ctx.ref(), self.vector) @@ -5167,6 +5191,9 @@ class AstMap: self.ctx = ctx Z3_ast_map_inc_ref(self.ctx.ref(), self.map) + def __deepcopy__(self, memo={}): + return AstMap(self.map, self.ctx) + def __del__(self): if self.map is not None and self.ctx.ref() is not None: Z3_ast_map_dec_ref(self.ctx.ref(), self.map) @@ -5282,6 +5309,9 @@ class FuncEntry: self.ctx = ctx Z3_func_entry_inc_ref(self.ctx.ref(), self.entry) + def __deepcopy__(self, memo={}): + return FuncEntry(self.entry, self.ctx) + def __del__(self): if self.ctx.ref() is not None: Z3_func_entry_dec_ref(self.ctx.ref(), self.entry) @@ -5388,6 +5418,9 @@ class FuncInterp(Z3PPObject): if self.f is not None: Z3_func_interp_inc_ref(self.ctx.ref(), self.f) + def __deepcopy__(self, memo={}): + return FuncInterp(self.f, self.ctx) + def __del__(self): if self.f is not None and self.ctx.ref() is not None: Z3_func_interp_dec_ref(self.ctx.ref(), self.f) @@ -5498,6 +5531,9 @@ class ModelRef(Z3PPObject): self.ctx = ctx Z3_model_inc_ref(self.ctx.ref(), self.model) + def __deepcopy__(self, memo={}): + return ModelRef(self.m, self.ctx) + def __del__(self): if self.ctx.ref() is not None: Z3_model_dec_ref(self.ctx.ref(), self.model) @@ -5774,6 +5810,9 @@ class Statistics: self.ctx = ctx Z3_stats_inc_ref(self.ctx.ref(), self.stats) + def __deepcopy__(self, memo={}): + return Statistics(self.stats, self.ctx) + def __del__(self): if self.ctx.ref() is not None: Z3_stats_dec_ref(self.ctx.ref(), self.stats) @@ -5908,6 +5947,9 @@ class CheckSatResult: def __init__(self, r): self.r = r + def __deepcopy__(self, memo={}): + return CheckSatResult(self.r) + def __eq__(self, other): return isinstance(other, CheckSatResult) and self.r == other.r @@ -5947,6 +5989,9 @@ class Solver(Z3PPObject): self.solver = solver Z3_solver_inc_ref(self.ctx.ref(), self.solver) + def __deepcopy__(self, memo={}): + return Solver(self.solver, self.ctx) + def __del__(self): if self.solver is not None and self.ctx.ref() is not None: Z3_solver_dec_ref(self.ctx.ref(), self.solver) @@ -6367,6 +6412,9 @@ class Fixedpoint(Z3PPObject): Z3_fixedpoint_inc_ref(self.ctx.ref(), self.fixedpoint) self.vars = [] + def __deepcopy__(self, memo={}): + return FixedPoint(self.fixedpoint, self.ctx) + def __del__(self): if self.fixedpoint is not None and self.ctx.ref() is not None: Z3_fixedpoint_dec_ref(self.ctx.ref(), self.fixedpoint) @@ -6741,6 +6789,9 @@ class Optimize(Z3PPObject): self.optimize = Z3_mk_optimize(self.ctx.ref()) Z3_optimize_inc_ref(self.ctx.ref(), self.optimize) + def __deepcopy__(self, memo={}): + return Optimize(self.optimize, self.ctx) + def __del__(self): if self.optimize is not None and self.ctx.ref() is not None: Z3_optimize_dec_ref(self.ctx.ref(), self.optimize) @@ -6893,6 +6944,9 @@ class ApplyResult(Z3PPObject): self.ctx = ctx Z3_apply_result_inc_ref(self.ctx.ref(), self.result) + def __deepcopy__(self, memo={}): + return ApplyResult(self.result, self.ctx) + def __del__(self): if self.ctx.ref() is not None: Z3_apply_result_dec_ref(self.ctx.ref(), self.result) @@ -7021,6 +7075,9 @@ class Tactic: raise Z3Exception("unknown tactic '%s'" % tactic) Z3_tactic_inc_ref(self.ctx.ref(), self.tactic) + def __deepcopy__(self, memo={}): + return Tactic(self.tactic, self.ctx) + def __del__(self): if self.tactic is not None and self.ctx.ref() is not None: Z3_tactic_dec_ref(self.ctx.ref(), self.tactic) @@ -7293,6 +7350,9 @@ class Probe: raise Z3Exception("unknown probe '%s'" % probe) Z3_probe_inc_ref(self.ctx.ref(), self.probe) + def __deepcopy__(self, memo={}): + return Probe(self.probe, self.ctx) + def __del__(self): if self.probe is not None and self.ctx.ref() is not None: Z3_probe_dec_ref(self.ctx.ref(), self.probe) From 903709b9c145b011533f3ab54b6c4ae22d7b935c Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Wed, 7 Jun 2017 17:09:01 +0100 Subject: [PATCH 005/159] [Doxygen] Fix bug where some header files were not being scanned. --- doc/z3api.cfg.in | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/z3api.cfg.in b/doc/z3api.cfg.in index 9e946aa7f..9c4b464c2 100644 --- a/doc/z3api.cfg.in +++ b/doc/z3api.cfg.in @@ -704,10 +704,13 @@ INPUT_ENCODING = UTF-8 FILE_PATTERNS = website.dox \ z3_api.h \ z3_algebraic.h \ + z3_ast_containers.h \ + z3_fixedpoint.h \ + z3_fpa.h \ + z3_interp.h \ + z3_optimization.h \ z3_polynomial.h \ z3_rcf.h \ - z3_interp.h \ - z3_fpa.h \ z3++.h \ @PYTHON_API_FILES@ @DOTNET_API_FILES@ @JAVA_API_FILES@ From 85c7f5d8655b6a1e3721fa8ec308c51ffe87ead2 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Wed, 7 Jun 2017 18:22:38 +0100 Subject: [PATCH 006/159] [Doxygen] Fix some Doxygen warnings for `z3_optimization.h` --- src/api/z3_optimization.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/z3_optimization.h b/src/api/z3_optimization.h index 795b4b8fd..f49e1b9ce 100644 --- a/src/api/z3_optimization.h +++ b/src/api/z3_optimization.h @@ -75,7 +75,7 @@ extern "C" { \brief Add a maximization constraint. \param c - context \param o - optimization context - \param a - arithmetical term + \param t - arithmetical term def_API('Z3_optimize_maximize', UINT, (_in(CONTEXT), _in(OPTIMIZE), _in(AST))) */ unsigned Z3_API Z3_optimize_maximize(Z3_context c, Z3_optimize o, Z3_ast t); @@ -84,7 +84,7 @@ extern "C" { \brief Add a minimization constraint. \param c - context \param o - optimization context - \param a - arithmetical term + \param t - arithmetical term def_API('Z3_optimize_minimize', UINT, (_in(CONTEXT), _in(OPTIMIZE), _in(AST))) */ From bcb3981c5fd1988778699f3b40db8e9ce0d8c4f5 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Wed, 7 Jun 2017 18:49:43 +0100 Subject: [PATCH 007/159] [Doxygen] Fixed mismatched `@{` and `@}` declaration which prevented the `capi` group from being declared properly. For example this prevented from `Z3_mk_solver()` from appearing in the `capi` group. --- src/api/z3_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 93da0b2c7..b862884c9 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -48,6 +48,7 @@ DEFINE_TYPE(Z3_rcf_num); /*@{*/ /** @name Types + @{ Most of the types in the C API are opaque pointers. @@ -5238,7 +5239,6 @@ extern "C" { def_API('Z3_get_error_msg', STRING, (_in(CONTEXT), _in(ERROR_CODE))) */ Z3_string Z3_API Z3_get_error_msg(Z3_context c, Z3_error_code err); - /*@}*/ /** \brief Return a string describing the given error code. From d5f646929ef3881a0f499f40981bd98d04894e82 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 10 Jun 2017 09:16:36 -0700 Subject: [PATCH 008/159] print success #1068 Signed-off-by: Nikolaj Bjorner --- src/cmd_context/basic_cmds.cpp | 2 +- src/opt/opt_cmds.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index a098f3c94..5731f890a 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -266,7 +266,7 @@ UNARY_CMD(pp_cmd, "display", "", "display the given term.", CPK_EXPR, expr ctx.regular_stream() << std::endl; }); -UNARY_CMD(echo_cmd, "echo", "", "display the given string", CPK_STRING, char const *, ctx.regular_stream() << arg << std::endl;); +UNARY_CMD(echo_cmd, "echo", "", "display the given string", CPK_STRING, char const *, ctx.regular_stream() << "\"" << arg << "\"" << std::endl;); class set_get_option_cmd : public cmd { diff --git a/src/opt/opt_cmds.cpp b/src/opt/opt_cmds.cpp index 571c26e2d..a5c163562 100644 --- a/src/opt/opt_cmds.cpp +++ b/src/opt/opt_cmds.cpp @@ -100,6 +100,7 @@ public: rational weight = ps().get_rat(symbol("weight"), rational::one()); symbol id = ps().get_sym(symbol("id"), symbol::null); get_opt(ctx, m_opt).add_soft_constraint(m_formula, weight, id); + ctx.print_success(); reset(ctx); } @@ -131,6 +132,7 @@ public: throw cmd_exception("malformed objective term: it cannot be a quantifier or bound variable"); } get_opt(ctx, m_opt).add_objective(to_app(t), m_is_max); + ctx.print_success(); } virtual void failure_cleanup(cmd_context & ctx) { From b8e8e090ad10b8557219ae6724ee215de7e7e76d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 10 Jun 2017 09:30:01 -0700 Subject: [PATCH 009/159] filter assumptions by membership in initial list #1065 Signed-off-by: Nikolaj Bjorner --- src/sat/sat_solver/inc_sat_solver.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index b9ed925b0..e9302bb35 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -597,16 +597,14 @@ private: extract_asm2dep(dep2asm, asm2dep); sat::literal_vector const& core = m_solver.get_core(); TRACE("sat", - dep2asm_t::iterator it2 = dep2asm.begin(); - dep2asm_t::iterator end2 = dep2asm.end(); - for (; it2 != end2; ++it2) { - tout << mk_pp(it2->m_key, m) << " |-> " << sat::literal(it2->m_value) << "\n"; + for (auto kv : dep2asm) { + tout << mk_pp(kv.m_key, m) << " |-> " << sat::literal(kv.m_value) << "\n"; } - tout << "core: "; - for (unsigned i = 0; i < core.size(); ++i) { - tout << core[i] << " "; + tout << "asm2fml: "; + for (auto kv : asm2fml) { + tout << mk_pp(kv.m_key, m) << " |-> " << mk_pp(kv.m_value, m) << "\n"; } - tout << "\n"; + tout << "core: "; for (auto c : core) tout << c << " "; tout << "\n"; ); m_core.reset(); @@ -615,8 +613,8 @@ private: VERIFY(asm2dep.find(core[i].index(), e)); if (asm2fml.contains(e)) { e = asm2fml.find(e); + m_core.push_back(e); } - m_core.push_back(e); } } From 8acb37e734f12cd889c297184ba84b256a936bce Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 10 Jun 2017 09:45:18 -0700 Subject: [PATCH 010/159] revert change to 1065 Signed-off-by: Nikolaj Bjorner --- src/sat/sat_solver/inc_sat_solver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index e9302bb35..b6904ef02 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -613,8 +613,8 @@ private: VERIFY(asm2dep.find(core[i].index(), e)); if (asm2fml.contains(e)) { e = asm2fml.find(e); - m_core.push_back(e); } + m_core.push_back(e); } } From f44a3e1bbcffafa9734b4d2f6292265501a14b45 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 10 Jun 2017 10:18:07 -0700 Subject: [PATCH 011/159] print_core as a function Signed-off-by: Nikolaj Bjorner --- src/cmd_context/basic_cmds.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index 5731f890a..72dfa7648 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -198,20 +198,21 @@ ATOMIC_CMD(get_proof_cmd, "get-proof", "retrieve proof", { } }); -#define PRINT_CORE() \ - ptr_vector core; \ - ctx.get_check_sat_result()->get_unsat_core(core); \ - ctx.regular_stream() << "("; \ - ptr_vector::const_iterator it = core.begin(); \ - ptr_vector::const_iterator end = core.end(); \ - for (bool first = true; it != end; ++it) { \ - if (first) \ - first = false; \ - else \ - ctx.regular_stream() << " "; \ - ctx.regular_stream() << mk_ismt2_pp(*it, ctx.m()); \ - } \ - ctx.regular_stream() << ")" << std::endl; \ +static void print_core(cmd_context& ctx) { + ptr_vector core; + ctx.get_check_sat_result()->get_unsat_core(core); + ctx.regular_stream() << "("; + ptr_vector::const_iterator it = core.begin(); + ptr_vector::const_iterator end = core.end(); + for (bool first = true; it != end; ++it) { + if (first) + first = false; + else + ctx.regular_stream() << " "; + ctx.regular_stream() << mk_ismt2_pp(*it, ctx.m()); + } + ctx.regular_stream() << ")" << std::endl; +} ATOMIC_CMD(get_unsat_core_cmd, "get-unsat-core", "retrieve unsat core", { if (!ctx.produce_unsat_cores()) @@ -219,7 +220,7 @@ ATOMIC_CMD(get_unsat_core_cmd, "get-unsat-core", "retrieve unsat core", { if (!ctx.has_manager() || ctx.cs_state() != cmd_context::css_unsat) throw cmd_exception("unsat core is not available"); - PRINT_CORE(); + print_core(ctx); }); ATOMIC_CMD(get_unsat_assumptions_cmd, "get-unsat-assumptions", "retrieve subset of assumptions sufficient for unsatisfiability", { @@ -228,7 +229,7 @@ ATOMIC_CMD(get_unsat_assumptions_cmd, "get-unsat-assumptions", "retrieve subset if (!ctx.has_manager() || ctx.cs_state() != cmd_context::css_unsat) { throw cmd_exception("unsat assumptions is not available"); } - PRINT_CORE(); + print_core(ctx); }); From c629dcc53f431c84c6d67027cf42c7bc468f7e99 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Sun, 11 Jun 2017 14:04:18 +0100 Subject: [PATCH 012/159] [Doxygen] Rewrite documentation of `Z3_mk_solver()` and `Z3_mk_simple_solver()` to try to make it clearer what the differences are between these APIs. This an attempt to address issues noted in #1035. --- src/api/z3_api.h | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index b862884c9..555e6127e 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -5795,9 +5795,35 @@ extern "C" { /** @name Solvers*/ /*@{*/ /** - \brief Create a new (incremental) solver. This solver also uses a - set of builtin tactics for handling the first check-sat command, and - check-sat commands that take more than a given number of milliseconds to be solved. + \brief Create a new solver. This solver is a "combined solver" (see + combined_solver module) that internally uses a non-incremental (solver1) and an + incremental solver (solver2). This combined solver changes its behaviour based + on how it is used and how its parameters are set. + + If the solver is used in a non incremental way (i.e. no calls to + `Z3_solver_push()` or `Z3_solver_pop()`, and no calls to + `Z3_solver_assert()` or `Z3_solver_assert_and_track()` after checking + satisfiability without an intervening `Z3_solver_reset()`) then solver1 + will be used. This solver will apply Z3's "default" tactic. + + The "default" tactic will attempt to probe the logic used by the + assertions and will apply a specialized tactic if one is supported. + Otherwise the general `(and-then simplify smt)` tactic will be used. + + If the solver is used in an incremental way then the combined solver + will switch to using solver2 (which behaves similarly to the general + "smt" tactic). + + Note however it is possible to set the `solver2_timeout`, + `solver2_unknown`, and `ignore_solver1` parameters of the combined + solver to change its behaviour. + + The function #Z3_solver_get_model retrieves a model if the + assertions is satisfiable (i.e., the result is \c + Z3_L_TRUE) and model construction is enabled. + The function #Z3_solver_get_model can also be used even + if the result is \c Z3_L_UNDEF, but the returned model + is not guaranteed to satisfy quantified assertions. \remark User must use #Z3_solver_inc_ref and #Z3_solver_dec_ref to manage solver objects. Even if the context was created using #Z3_mk_context instead of #Z3_mk_context_rc. @@ -5807,7 +5833,17 @@ extern "C" { Z3_solver Z3_API Z3_mk_solver(Z3_context c); /** - \brief Create a new (incremental) solver. + \brief Create a new incremental solver. + + This is equivalent to applying the "smt" tactic. + + Unlike `Z3_mk_solver()` this solver + - Does not attempt to apply any logic specific tactics. + - Does not changes its behaviour based on whether it used + incrementally/non-incrementally. + + Note that these differences can result in very different performance + compared to `Z3_mk_solver()`. The function #Z3_solver_get_model retrieves a model if the assertions is satisfiable (i.e., the result is \c From f5b54f042c65cc15ee92d15aaa686623787b5ab1 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 11 Jun 2017 11:40:39 -0700 Subject: [PATCH 013/159] apply correction by ddcc #1069 Signed-off-by: Nikolaj Bjorner --- src/api/z3_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 555e6127e..63f1d15ff 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -5839,7 +5839,7 @@ extern "C" { Unlike `Z3_mk_solver()` this solver - Does not attempt to apply any logic specific tactics. - - Does not changes its behaviour based on whether it used + - Does not change its behaviour based on whether it used incrementally/non-incrementally. Note that these differences can result in very different performance From f0fa439c4871a7c6c08529a97bb60f674cf0d68f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 11 Jun 2017 17:17:47 -0700 Subject: [PATCH 014/159] escaping names in get-assignment #1061 Signed-off-by: Nikolaj Bjorner --- src/cmd_context/basic_cmds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index 72dfa7648..35e157af5 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -149,7 +149,7 @@ ATOMIC_CMD(get_assignment_cmd, "get-assignment", "retrieve assignment", { first = false; else ctx.regular_stream() << " "; - ctx.regular_stream() << "(" << name << " " << (ctx.m().is_true(val) ? "true" : "false") << ")"; + ctx.regular_stream() << "(" << escaped(name.str().c_str()) << " " << (ctx.m().is_true(val) ? "true" : "false") << ")"; } } } From 4b517b96df66c87b46a1f9c9b2e8a2d26ed0195b Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Mon, 12 Jun 2017 10:21:50 +0100 Subject: [PATCH 015/159] [CMake] Move CMake files into their intended location so the `contrib/cmake/bootstrap.py` script no longer needs to be executed. The previous location of the CMake files was a compromise proposed by @agurfinkel in #461. While this has served us well (allowing progress to be made) over time limitations of this approach have appeared. The main problem is that doing many git operations (e.g. pull, rebase) means the CMake files don't get updated unless the user remembers to run the script. This can lead to broken and confusing build system behaviour. This commit only does the file moving and necessary changes to `.gitignore`. Other changes will be done in subsequent commits. --- .gitignore | 11 ----------- {contrib/cmake/cmake => cmake}/Z3Config.cmake.in | 0 .../cmake/cmake => cmake}/cmake_uninstall.cmake.in | 0 {contrib/cmake/cmake => cmake}/compiler_lto.cmake | 0 .../cmake/cmake => cmake}/compiler_warnings.cmake | 0 .../cxx_compiler_flags_overrides.cmake | 0 {contrib/cmake/cmake => cmake}/git_utils.cmake | 0 .../cmake => cmake}/modules/FindDotNetToolchain.cmake | 0 {contrib/cmake/cmake => cmake}/modules/FindGMP.cmake | 0 .../cmake/cmake => cmake}/msvc_legacy_quirks.cmake | 0 .../cmake/cmake => cmake}/target_arch_detect.cmake | 0 {contrib/cmake/cmake => cmake}/target_arch_detect.cpp | 0 {contrib/cmake/cmake => cmake}/z3_add_component.cmake | 0 {contrib/cmake/cmake => cmake}/z3_add_cxx_flag.cmake | 0 .../z3_append_linker_flag_list_to_target.cmake | 0 {contrib/cmake/doc => doc}/CMakeLists.txt | 0 {contrib/cmake/examples => examples}/CMakeLists.txt | 0 .../cmake/examples => examples}/c++/CMakeLists.txt | 0 {contrib/cmake/examples => examples}/c/CMakeLists.txt | 0 .../cmake/examples => examples}/python/CMakeLists.txt | 0 .../cmake/examples => examples}/tptp/CMakeLists.txt | 0 {contrib/cmake/src => src}/CMakeLists.txt | 0 .../cmake/src => src}/ackermannization/CMakeLists.txt | 0 {contrib/cmake/src => src}/api/CMakeLists.txt | 0 {contrib/cmake/src => src}/api/dll/CMakeLists.txt | 0 {contrib/cmake/src => src}/api/dotnet/CMakeLists.txt | 0 .../src => src}/api/dotnet/cmake_install_gac.cmake.in | 0 .../api/dotnet/cmake_uninstall_gac.cmake.in | 0 {contrib/cmake/src => src}/api/java/CMakeLists.txt | 0 {contrib/cmake/src => src}/api/python/CMakeLists.txt | 0 {contrib/cmake/src => src}/ast/CMakeLists.txt | 0 {contrib/cmake/src => src}/ast/fpa/CMakeLists.txt | 0 {contrib/cmake/src => src}/ast/macros/CMakeLists.txt | 0 .../cmake/src => src}/ast/normal_forms/CMakeLists.txt | 0 {contrib/cmake/src => src}/ast/pattern/CMakeLists.txt | 0 .../src => src}/ast/proof_checker/CMakeLists.txt | 0 .../cmake/src => src}/ast/rewriter/CMakeLists.txt | 0 .../ast/rewriter/bit_blaster/CMakeLists.txt | 0 .../cmake/src => src}/ast/simplifier/CMakeLists.txt | 0 .../cmake/src => src}/ast/substitution/CMakeLists.txt | 0 {contrib/cmake/src => src}/cmd_context/CMakeLists.txt | 0 .../src => src}/cmd_context/extra_cmds/CMakeLists.txt | 0 {contrib/cmake/src => src}/duality/CMakeLists.txt | 0 {contrib/cmake/src => src}/interp/CMakeLists.txt | 0 .../cmake/src => src}/math/automata/CMakeLists.txt | 0 {contrib/cmake/src => src}/math/euclid/CMakeLists.txt | 0 .../cmake/src => src}/math/grobner/CMakeLists.txt | 0 .../cmake/src => src}/math/hilbert/CMakeLists.txt | 0 .../cmake/src => src}/math/interval/CMakeLists.txt | 0 .../cmake/src => src}/math/polynomial/CMakeLists.txt | 0 .../cmake/src => src}/math/realclosure/CMakeLists.txt | 0 .../cmake/src => src}/math/simplex/CMakeLists.txt | 0 .../cmake/src => src}/math/subpaving/CMakeLists.txt | 0 .../src => src}/math/subpaving/tactic/CMakeLists.txt | 0 {contrib/cmake/src => src}/model/CMakeLists.txt | 0 {contrib/cmake/src => src}/muz/base/CMakeLists.txt | 0 {contrib/cmake/src => src}/muz/bmc/CMakeLists.txt | 0 {contrib/cmake/src => src}/muz/clp/CMakeLists.txt | 0 .../cmake/src => src}/muz/dataflow/CMakeLists.txt | 0 {contrib/cmake/src => src}/muz/ddnf/CMakeLists.txt | 0 {contrib/cmake/src => src}/muz/duality/CMakeLists.txt | 0 {contrib/cmake/src => src}/muz/fp/CMakeLists.txt | 0 {contrib/cmake/src => src}/muz/pdr/CMakeLists.txt | 0 {contrib/cmake/src => src}/muz/rel/CMakeLists.txt | 0 {contrib/cmake/src => src}/muz/tab/CMakeLists.txt | 0 .../cmake/src => src}/muz/transforms/CMakeLists.txt | 0 {contrib/cmake/src => src}/nlsat/CMakeLists.txt | 0 .../cmake/src => src}/nlsat/tactic/CMakeLists.txt | 0 {contrib/cmake/src => src}/opt/CMakeLists.txt | 0 {contrib/cmake/src => src}/parsers/smt/CMakeLists.txt | 0 .../cmake/src => src}/parsers/smt2/CMakeLists.txt | 0 .../cmake/src => src}/parsers/util/CMakeLists.txt | 0 {contrib/cmake/src => src}/qe/CMakeLists.txt | 0 {contrib/cmake/src => src}/sat/CMakeLists.txt | 0 .../cmake/src => src}/sat/sat_solver/CMakeLists.txt | 0 {contrib/cmake/src => src}/sat/tactic/CMakeLists.txt | 0 {contrib/cmake/src => src}/shell/CMakeLists.txt | 0 {contrib/cmake/src => src}/smt/CMakeLists.txt | 0 {contrib/cmake/src => src}/smt/params/CMakeLists.txt | 0 .../cmake/src => src}/smt/proto_model/CMakeLists.txt | 0 {contrib/cmake/src => src}/smt/tactic/CMakeLists.txt | 0 {contrib/cmake/src => src}/solver/CMakeLists.txt | 0 {contrib/cmake/src => src}/tactic/CMakeLists.txt | 0 {contrib/cmake/src => src}/tactic/aig/CMakeLists.txt | 0 .../cmake/src => src}/tactic/arith/CMakeLists.txt | 0 {contrib/cmake/src => src}/tactic/bv/CMakeLists.txt | 0 {contrib/cmake/src => src}/tactic/core/CMakeLists.txt | 0 {contrib/cmake/src => src}/tactic/fpa/CMakeLists.txt | 0 .../cmake/src => src}/tactic/nlsat_smt/CMakeLists.txt | 0 .../cmake/src => src}/tactic/portfolio/CMakeLists.txt | 0 {contrib/cmake/src => src}/tactic/sls/CMakeLists.txt | 0 .../cmake/src => src}/tactic/smtlogics/CMakeLists.txt | 0 {contrib/cmake/src => src}/tactic/ufbv/CMakeLists.txt | 0 {contrib/cmake/src => src}/test/CMakeLists.txt | 0 .../cmake/src => src}/test/fuzzing/CMakeLists.txt | 0 {contrib/cmake/src => src}/util/CMakeLists.txt | 0 {contrib/cmake/src => src}/util/lp/CMakeLists.txt | 0 97 files changed, 11 deletions(-) rename {contrib/cmake/cmake => cmake}/Z3Config.cmake.in (100%) rename {contrib/cmake/cmake => cmake}/cmake_uninstall.cmake.in (100%) rename {contrib/cmake/cmake => cmake}/compiler_lto.cmake (100%) rename {contrib/cmake/cmake => cmake}/compiler_warnings.cmake (100%) rename {contrib/cmake/cmake => cmake}/cxx_compiler_flags_overrides.cmake (100%) rename {contrib/cmake/cmake => cmake}/git_utils.cmake (100%) rename {contrib/cmake/cmake => cmake}/modules/FindDotNetToolchain.cmake (100%) rename {contrib/cmake/cmake => cmake}/modules/FindGMP.cmake (100%) rename {contrib/cmake/cmake => cmake}/msvc_legacy_quirks.cmake (100%) rename {contrib/cmake/cmake => cmake}/target_arch_detect.cmake (100%) rename {contrib/cmake/cmake => cmake}/target_arch_detect.cpp (100%) rename {contrib/cmake/cmake => cmake}/z3_add_component.cmake (100%) rename {contrib/cmake/cmake => cmake}/z3_add_cxx_flag.cmake (100%) rename {contrib/cmake/cmake => cmake}/z3_append_linker_flag_list_to_target.cmake (100%) rename {contrib/cmake/doc => doc}/CMakeLists.txt (100%) rename {contrib/cmake/examples => examples}/CMakeLists.txt (100%) rename {contrib/cmake/examples => examples}/c++/CMakeLists.txt (100%) rename {contrib/cmake/examples => examples}/c/CMakeLists.txt (100%) rename {contrib/cmake/examples => examples}/python/CMakeLists.txt (100%) rename {contrib/cmake/examples => examples}/tptp/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/ackermannization/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/api/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/api/dll/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/api/dotnet/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/api/dotnet/cmake_install_gac.cmake.in (100%) rename {contrib/cmake/src => src}/api/dotnet/cmake_uninstall_gac.cmake.in (100%) rename {contrib/cmake/src => src}/api/java/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/api/python/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/ast/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/ast/fpa/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/ast/macros/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/ast/normal_forms/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/ast/pattern/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/ast/proof_checker/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/ast/rewriter/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/ast/rewriter/bit_blaster/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/ast/simplifier/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/ast/substitution/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/cmd_context/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/cmd_context/extra_cmds/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/duality/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/interp/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/math/automata/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/math/euclid/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/math/grobner/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/math/hilbert/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/math/interval/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/math/polynomial/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/math/realclosure/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/math/simplex/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/math/subpaving/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/math/subpaving/tactic/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/model/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/muz/base/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/muz/bmc/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/muz/clp/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/muz/dataflow/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/muz/ddnf/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/muz/duality/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/muz/fp/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/muz/pdr/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/muz/rel/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/muz/tab/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/muz/transforms/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/nlsat/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/nlsat/tactic/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/opt/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/parsers/smt/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/parsers/smt2/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/parsers/util/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/qe/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/sat/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/sat/sat_solver/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/sat/tactic/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/shell/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/smt/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/smt/params/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/smt/proto_model/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/smt/tactic/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/solver/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/tactic/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/tactic/aig/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/tactic/arith/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/tactic/bv/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/tactic/core/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/tactic/fpa/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/tactic/nlsat_smt/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/tactic/portfolio/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/tactic/sls/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/tactic/smtlogics/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/tactic/ufbv/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/test/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/test/fuzzing/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/util/CMakeLists.txt (100%) rename {contrib/cmake/src => src}/util/lp/CMakeLists.txt (100%) diff --git a/.gitignore b/.gitignore index cc1c2a754..b7e4a0186 100644 --- a/.gitignore +++ b/.gitignore @@ -75,14 +75,3 @@ src/api/ml/z3.mllib *.bak doc/api doc/code - -# CMake files copied over by the ``contrib/cmake/boostrap.py`` script -# See #461 -examples/CMakeLists.txt -examples/*/CMakeLists.txt -src/CMakeLists.txt -src/*/CMakeLists.txt -src/*/*/CMakeLists.txt -src/*/*/*/CMakeLists.txt -src/api/dotnet/cmake_install_gac.cmake.in -src/api/dotnet/cmake_uninstall_gac.cmake.in diff --git a/contrib/cmake/cmake/Z3Config.cmake.in b/cmake/Z3Config.cmake.in similarity index 100% rename from contrib/cmake/cmake/Z3Config.cmake.in rename to cmake/Z3Config.cmake.in diff --git a/contrib/cmake/cmake/cmake_uninstall.cmake.in b/cmake/cmake_uninstall.cmake.in similarity index 100% rename from contrib/cmake/cmake/cmake_uninstall.cmake.in rename to cmake/cmake_uninstall.cmake.in diff --git a/contrib/cmake/cmake/compiler_lto.cmake b/cmake/compiler_lto.cmake similarity index 100% rename from contrib/cmake/cmake/compiler_lto.cmake rename to cmake/compiler_lto.cmake diff --git a/contrib/cmake/cmake/compiler_warnings.cmake b/cmake/compiler_warnings.cmake similarity index 100% rename from contrib/cmake/cmake/compiler_warnings.cmake rename to cmake/compiler_warnings.cmake diff --git a/contrib/cmake/cmake/cxx_compiler_flags_overrides.cmake b/cmake/cxx_compiler_flags_overrides.cmake similarity index 100% rename from contrib/cmake/cmake/cxx_compiler_flags_overrides.cmake rename to cmake/cxx_compiler_flags_overrides.cmake diff --git a/contrib/cmake/cmake/git_utils.cmake b/cmake/git_utils.cmake similarity index 100% rename from contrib/cmake/cmake/git_utils.cmake rename to cmake/git_utils.cmake diff --git a/contrib/cmake/cmake/modules/FindDotNetToolchain.cmake b/cmake/modules/FindDotNetToolchain.cmake similarity index 100% rename from contrib/cmake/cmake/modules/FindDotNetToolchain.cmake rename to cmake/modules/FindDotNetToolchain.cmake diff --git a/contrib/cmake/cmake/modules/FindGMP.cmake b/cmake/modules/FindGMP.cmake similarity index 100% rename from contrib/cmake/cmake/modules/FindGMP.cmake rename to cmake/modules/FindGMP.cmake diff --git a/contrib/cmake/cmake/msvc_legacy_quirks.cmake b/cmake/msvc_legacy_quirks.cmake similarity index 100% rename from contrib/cmake/cmake/msvc_legacy_quirks.cmake rename to cmake/msvc_legacy_quirks.cmake diff --git a/contrib/cmake/cmake/target_arch_detect.cmake b/cmake/target_arch_detect.cmake similarity index 100% rename from contrib/cmake/cmake/target_arch_detect.cmake rename to cmake/target_arch_detect.cmake diff --git a/contrib/cmake/cmake/target_arch_detect.cpp b/cmake/target_arch_detect.cpp similarity index 100% rename from contrib/cmake/cmake/target_arch_detect.cpp rename to cmake/target_arch_detect.cpp diff --git a/contrib/cmake/cmake/z3_add_component.cmake b/cmake/z3_add_component.cmake similarity index 100% rename from contrib/cmake/cmake/z3_add_component.cmake rename to cmake/z3_add_component.cmake diff --git a/contrib/cmake/cmake/z3_add_cxx_flag.cmake b/cmake/z3_add_cxx_flag.cmake similarity index 100% rename from contrib/cmake/cmake/z3_add_cxx_flag.cmake rename to cmake/z3_add_cxx_flag.cmake diff --git a/contrib/cmake/cmake/z3_append_linker_flag_list_to_target.cmake b/cmake/z3_append_linker_flag_list_to_target.cmake similarity index 100% rename from contrib/cmake/cmake/z3_append_linker_flag_list_to_target.cmake rename to cmake/z3_append_linker_flag_list_to_target.cmake diff --git a/contrib/cmake/doc/CMakeLists.txt b/doc/CMakeLists.txt similarity index 100% rename from contrib/cmake/doc/CMakeLists.txt rename to doc/CMakeLists.txt diff --git a/contrib/cmake/examples/CMakeLists.txt b/examples/CMakeLists.txt similarity index 100% rename from contrib/cmake/examples/CMakeLists.txt rename to examples/CMakeLists.txt diff --git a/contrib/cmake/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt similarity index 100% rename from contrib/cmake/examples/c++/CMakeLists.txt rename to examples/c++/CMakeLists.txt diff --git a/contrib/cmake/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt similarity index 100% rename from contrib/cmake/examples/c/CMakeLists.txt rename to examples/c/CMakeLists.txt diff --git a/contrib/cmake/examples/python/CMakeLists.txt b/examples/python/CMakeLists.txt similarity index 100% rename from contrib/cmake/examples/python/CMakeLists.txt rename to examples/python/CMakeLists.txt diff --git a/contrib/cmake/examples/tptp/CMakeLists.txt b/examples/tptp/CMakeLists.txt similarity index 100% rename from contrib/cmake/examples/tptp/CMakeLists.txt rename to examples/tptp/CMakeLists.txt diff --git a/contrib/cmake/src/CMakeLists.txt b/src/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/CMakeLists.txt rename to src/CMakeLists.txt diff --git a/contrib/cmake/src/ackermannization/CMakeLists.txt b/src/ackermannization/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ackermannization/CMakeLists.txt rename to src/ackermannization/CMakeLists.txt diff --git a/contrib/cmake/src/api/CMakeLists.txt b/src/api/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/api/CMakeLists.txt rename to src/api/CMakeLists.txt diff --git a/contrib/cmake/src/api/dll/CMakeLists.txt b/src/api/dll/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/api/dll/CMakeLists.txt rename to src/api/dll/CMakeLists.txt diff --git a/contrib/cmake/src/api/dotnet/CMakeLists.txt b/src/api/dotnet/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/api/dotnet/CMakeLists.txt rename to src/api/dotnet/CMakeLists.txt diff --git a/contrib/cmake/src/api/dotnet/cmake_install_gac.cmake.in b/src/api/dotnet/cmake_install_gac.cmake.in similarity index 100% rename from contrib/cmake/src/api/dotnet/cmake_install_gac.cmake.in rename to src/api/dotnet/cmake_install_gac.cmake.in diff --git a/contrib/cmake/src/api/dotnet/cmake_uninstall_gac.cmake.in b/src/api/dotnet/cmake_uninstall_gac.cmake.in similarity index 100% rename from contrib/cmake/src/api/dotnet/cmake_uninstall_gac.cmake.in rename to src/api/dotnet/cmake_uninstall_gac.cmake.in diff --git a/contrib/cmake/src/api/java/CMakeLists.txt b/src/api/java/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/api/java/CMakeLists.txt rename to src/api/java/CMakeLists.txt diff --git a/contrib/cmake/src/api/python/CMakeLists.txt b/src/api/python/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/api/python/CMakeLists.txt rename to src/api/python/CMakeLists.txt diff --git a/contrib/cmake/src/ast/CMakeLists.txt b/src/ast/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/CMakeLists.txt rename to src/ast/CMakeLists.txt diff --git a/contrib/cmake/src/ast/fpa/CMakeLists.txt b/src/ast/fpa/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/fpa/CMakeLists.txt rename to src/ast/fpa/CMakeLists.txt diff --git a/contrib/cmake/src/ast/macros/CMakeLists.txt b/src/ast/macros/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/macros/CMakeLists.txt rename to src/ast/macros/CMakeLists.txt diff --git a/contrib/cmake/src/ast/normal_forms/CMakeLists.txt b/src/ast/normal_forms/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/normal_forms/CMakeLists.txt rename to src/ast/normal_forms/CMakeLists.txt diff --git a/contrib/cmake/src/ast/pattern/CMakeLists.txt b/src/ast/pattern/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/pattern/CMakeLists.txt rename to src/ast/pattern/CMakeLists.txt diff --git a/contrib/cmake/src/ast/proof_checker/CMakeLists.txt b/src/ast/proof_checker/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/proof_checker/CMakeLists.txt rename to src/ast/proof_checker/CMakeLists.txt diff --git a/contrib/cmake/src/ast/rewriter/CMakeLists.txt b/src/ast/rewriter/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/rewriter/CMakeLists.txt rename to src/ast/rewriter/CMakeLists.txt diff --git a/contrib/cmake/src/ast/rewriter/bit_blaster/CMakeLists.txt b/src/ast/rewriter/bit_blaster/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/rewriter/bit_blaster/CMakeLists.txt rename to src/ast/rewriter/bit_blaster/CMakeLists.txt diff --git a/contrib/cmake/src/ast/simplifier/CMakeLists.txt b/src/ast/simplifier/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/simplifier/CMakeLists.txt rename to src/ast/simplifier/CMakeLists.txt diff --git a/contrib/cmake/src/ast/substitution/CMakeLists.txt b/src/ast/substitution/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/ast/substitution/CMakeLists.txt rename to src/ast/substitution/CMakeLists.txt diff --git a/contrib/cmake/src/cmd_context/CMakeLists.txt b/src/cmd_context/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/cmd_context/CMakeLists.txt rename to src/cmd_context/CMakeLists.txt diff --git a/contrib/cmake/src/cmd_context/extra_cmds/CMakeLists.txt b/src/cmd_context/extra_cmds/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/cmd_context/extra_cmds/CMakeLists.txt rename to src/cmd_context/extra_cmds/CMakeLists.txt diff --git a/contrib/cmake/src/duality/CMakeLists.txt b/src/duality/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/duality/CMakeLists.txt rename to src/duality/CMakeLists.txt diff --git a/contrib/cmake/src/interp/CMakeLists.txt b/src/interp/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/interp/CMakeLists.txt rename to src/interp/CMakeLists.txt diff --git a/contrib/cmake/src/math/automata/CMakeLists.txt b/src/math/automata/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/automata/CMakeLists.txt rename to src/math/automata/CMakeLists.txt diff --git a/contrib/cmake/src/math/euclid/CMakeLists.txt b/src/math/euclid/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/euclid/CMakeLists.txt rename to src/math/euclid/CMakeLists.txt diff --git a/contrib/cmake/src/math/grobner/CMakeLists.txt b/src/math/grobner/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/grobner/CMakeLists.txt rename to src/math/grobner/CMakeLists.txt diff --git a/contrib/cmake/src/math/hilbert/CMakeLists.txt b/src/math/hilbert/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/hilbert/CMakeLists.txt rename to src/math/hilbert/CMakeLists.txt diff --git a/contrib/cmake/src/math/interval/CMakeLists.txt b/src/math/interval/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/interval/CMakeLists.txt rename to src/math/interval/CMakeLists.txt diff --git a/contrib/cmake/src/math/polynomial/CMakeLists.txt b/src/math/polynomial/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/polynomial/CMakeLists.txt rename to src/math/polynomial/CMakeLists.txt diff --git a/contrib/cmake/src/math/realclosure/CMakeLists.txt b/src/math/realclosure/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/realclosure/CMakeLists.txt rename to src/math/realclosure/CMakeLists.txt diff --git a/contrib/cmake/src/math/simplex/CMakeLists.txt b/src/math/simplex/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/simplex/CMakeLists.txt rename to src/math/simplex/CMakeLists.txt diff --git a/contrib/cmake/src/math/subpaving/CMakeLists.txt b/src/math/subpaving/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/subpaving/CMakeLists.txt rename to src/math/subpaving/CMakeLists.txt diff --git a/contrib/cmake/src/math/subpaving/tactic/CMakeLists.txt b/src/math/subpaving/tactic/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/math/subpaving/tactic/CMakeLists.txt rename to src/math/subpaving/tactic/CMakeLists.txt diff --git a/contrib/cmake/src/model/CMakeLists.txt b/src/model/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/model/CMakeLists.txt rename to src/model/CMakeLists.txt diff --git a/contrib/cmake/src/muz/base/CMakeLists.txt b/src/muz/base/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/base/CMakeLists.txt rename to src/muz/base/CMakeLists.txt diff --git a/contrib/cmake/src/muz/bmc/CMakeLists.txt b/src/muz/bmc/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/bmc/CMakeLists.txt rename to src/muz/bmc/CMakeLists.txt diff --git a/contrib/cmake/src/muz/clp/CMakeLists.txt b/src/muz/clp/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/clp/CMakeLists.txt rename to src/muz/clp/CMakeLists.txt diff --git a/contrib/cmake/src/muz/dataflow/CMakeLists.txt b/src/muz/dataflow/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/dataflow/CMakeLists.txt rename to src/muz/dataflow/CMakeLists.txt diff --git a/contrib/cmake/src/muz/ddnf/CMakeLists.txt b/src/muz/ddnf/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/ddnf/CMakeLists.txt rename to src/muz/ddnf/CMakeLists.txt diff --git a/contrib/cmake/src/muz/duality/CMakeLists.txt b/src/muz/duality/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/duality/CMakeLists.txt rename to src/muz/duality/CMakeLists.txt diff --git a/contrib/cmake/src/muz/fp/CMakeLists.txt b/src/muz/fp/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/fp/CMakeLists.txt rename to src/muz/fp/CMakeLists.txt diff --git a/contrib/cmake/src/muz/pdr/CMakeLists.txt b/src/muz/pdr/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/pdr/CMakeLists.txt rename to src/muz/pdr/CMakeLists.txt diff --git a/contrib/cmake/src/muz/rel/CMakeLists.txt b/src/muz/rel/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/rel/CMakeLists.txt rename to src/muz/rel/CMakeLists.txt diff --git a/contrib/cmake/src/muz/tab/CMakeLists.txt b/src/muz/tab/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/tab/CMakeLists.txt rename to src/muz/tab/CMakeLists.txt diff --git a/contrib/cmake/src/muz/transforms/CMakeLists.txt b/src/muz/transforms/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/muz/transforms/CMakeLists.txt rename to src/muz/transforms/CMakeLists.txt diff --git a/contrib/cmake/src/nlsat/CMakeLists.txt b/src/nlsat/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/nlsat/CMakeLists.txt rename to src/nlsat/CMakeLists.txt diff --git a/contrib/cmake/src/nlsat/tactic/CMakeLists.txt b/src/nlsat/tactic/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/nlsat/tactic/CMakeLists.txt rename to src/nlsat/tactic/CMakeLists.txt diff --git a/contrib/cmake/src/opt/CMakeLists.txt b/src/opt/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/opt/CMakeLists.txt rename to src/opt/CMakeLists.txt diff --git a/contrib/cmake/src/parsers/smt/CMakeLists.txt b/src/parsers/smt/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/parsers/smt/CMakeLists.txt rename to src/parsers/smt/CMakeLists.txt diff --git a/contrib/cmake/src/parsers/smt2/CMakeLists.txt b/src/parsers/smt2/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/parsers/smt2/CMakeLists.txt rename to src/parsers/smt2/CMakeLists.txt diff --git a/contrib/cmake/src/parsers/util/CMakeLists.txt b/src/parsers/util/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/parsers/util/CMakeLists.txt rename to src/parsers/util/CMakeLists.txt diff --git a/contrib/cmake/src/qe/CMakeLists.txt b/src/qe/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/qe/CMakeLists.txt rename to src/qe/CMakeLists.txt diff --git a/contrib/cmake/src/sat/CMakeLists.txt b/src/sat/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/sat/CMakeLists.txt rename to src/sat/CMakeLists.txt diff --git a/contrib/cmake/src/sat/sat_solver/CMakeLists.txt b/src/sat/sat_solver/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/sat/sat_solver/CMakeLists.txt rename to src/sat/sat_solver/CMakeLists.txt diff --git a/contrib/cmake/src/sat/tactic/CMakeLists.txt b/src/sat/tactic/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/sat/tactic/CMakeLists.txt rename to src/sat/tactic/CMakeLists.txt diff --git a/contrib/cmake/src/shell/CMakeLists.txt b/src/shell/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/shell/CMakeLists.txt rename to src/shell/CMakeLists.txt diff --git a/contrib/cmake/src/smt/CMakeLists.txt b/src/smt/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/smt/CMakeLists.txt rename to src/smt/CMakeLists.txt diff --git a/contrib/cmake/src/smt/params/CMakeLists.txt b/src/smt/params/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/smt/params/CMakeLists.txt rename to src/smt/params/CMakeLists.txt diff --git a/contrib/cmake/src/smt/proto_model/CMakeLists.txt b/src/smt/proto_model/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/smt/proto_model/CMakeLists.txt rename to src/smt/proto_model/CMakeLists.txt diff --git a/contrib/cmake/src/smt/tactic/CMakeLists.txt b/src/smt/tactic/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/smt/tactic/CMakeLists.txt rename to src/smt/tactic/CMakeLists.txt diff --git a/contrib/cmake/src/solver/CMakeLists.txt b/src/solver/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/solver/CMakeLists.txt rename to src/solver/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/CMakeLists.txt b/src/tactic/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/tactic/CMakeLists.txt rename to src/tactic/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/aig/CMakeLists.txt b/src/tactic/aig/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/tactic/aig/CMakeLists.txt rename to src/tactic/aig/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/arith/CMakeLists.txt b/src/tactic/arith/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/tactic/arith/CMakeLists.txt rename to src/tactic/arith/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/bv/CMakeLists.txt b/src/tactic/bv/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/tactic/bv/CMakeLists.txt rename to src/tactic/bv/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/core/CMakeLists.txt b/src/tactic/core/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/tactic/core/CMakeLists.txt rename to src/tactic/core/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/fpa/CMakeLists.txt b/src/tactic/fpa/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/tactic/fpa/CMakeLists.txt rename to src/tactic/fpa/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/nlsat_smt/CMakeLists.txt b/src/tactic/nlsat_smt/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/tactic/nlsat_smt/CMakeLists.txt rename to src/tactic/nlsat_smt/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/portfolio/CMakeLists.txt b/src/tactic/portfolio/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/tactic/portfolio/CMakeLists.txt rename to src/tactic/portfolio/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/sls/CMakeLists.txt b/src/tactic/sls/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/tactic/sls/CMakeLists.txt rename to src/tactic/sls/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/smtlogics/CMakeLists.txt b/src/tactic/smtlogics/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/tactic/smtlogics/CMakeLists.txt rename to src/tactic/smtlogics/CMakeLists.txt diff --git a/contrib/cmake/src/tactic/ufbv/CMakeLists.txt b/src/tactic/ufbv/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/tactic/ufbv/CMakeLists.txt rename to src/tactic/ufbv/CMakeLists.txt diff --git a/contrib/cmake/src/test/CMakeLists.txt b/src/test/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/test/CMakeLists.txt rename to src/test/CMakeLists.txt diff --git a/contrib/cmake/src/test/fuzzing/CMakeLists.txt b/src/test/fuzzing/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/test/fuzzing/CMakeLists.txt rename to src/test/fuzzing/CMakeLists.txt diff --git a/contrib/cmake/src/util/CMakeLists.txt b/src/util/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/util/CMakeLists.txt rename to src/util/CMakeLists.txt diff --git a/contrib/cmake/src/util/lp/CMakeLists.txt b/src/util/lp/CMakeLists.txt similarity index 100% rename from contrib/cmake/src/util/lp/CMakeLists.txt rename to src/util/lp/CMakeLists.txt From 5be503798ff97f8f9249a46145be23955a2e41ae Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Mon, 12 Jun 2017 10:29:01 +0100 Subject: [PATCH 016/159] [CMake] Remove bootstrap check. Now that the CMake files are in their correct location we don't need it anymore. --- CMakeLists.txt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7400f67e2..5ed7ee06a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,16 +14,6 @@ if (POLICY CMP0054) cmake_policy(SET CMP0054 OLD) endif() -# Provide a friendly message if the user hasn't run the bootstrap script -# to copy all the CMake files into their correct location. -# It is unfortunate that we have to do this, see #461 for the discussion -# on this. -if (NOT (EXISTS "${CMAKE_SOURCE_DIR}/src/CMakeLists.txt")) - message(FATAL_ERROR "Cannot find \"${CMAKE_SOURCE_DIR}/src/CMakeLists.txt\"" - ". This probably means you need to run" - "``python contrib/cmake/bootstrap.py create``") -endif() - set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake") project(Z3 CXX) From 5c3b11f034ff0550aaced0b61266382edb28ba9c Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Mon, 12 Jun 2017 10:39:49 +0100 Subject: [PATCH 017/159] [CMake] Modify `contrib/cmake/bootstrap.py` to do nothing except print a warning. Now that the CMake files have been moved into their intended location it is no longer necessary for this script to exist. However we do not want to break out-of-tree scripts that build Z3 using CMake to suddenly break. So the script has been modified to do nothing except print a warning. Eventually we should remove this script. --- contrib/cmake/bootstrap.py | 233 ++----------------------------------- 1 file changed, 10 insertions(+), 223 deletions(-) diff --git a/contrib/cmake/bootstrap.py b/contrib/cmake/bootstrap.py index a3c81fb25..dac08b383 100755 --- a/contrib/cmake/bootstrap.py +++ b/contrib/cmake/bootstrap.py @@ -1,25 +1,13 @@ #!/usr/bin/env python """ -This script is used to copy or delete the -CMake build system files from the contrib/cmake -folder into the their correct location in the Z3 -repository. +This script is an artifact of compromise that was +made when the CMake build system was first introduced +(see #461). -It offers two modes - -* create - This will symlink the ``cmake`` directory and copy (or hard link) -the appropriate files into their correct locations in the repository. - -* remove - This will remove the symlinked ``cmake`` -directory and remove the files added by the above -methods. - -This has the advantage -that editing the hard link edits the underlying file -(making development easier because copying files is -not neccessary) and CMake will regenerate correctly -because the modification time stamps will be correct. +This script now does nothing. It remains only to not +break out-of-tree scripts that build Z3 using CMake. +Eventually this script will be removed. """ import argparse import logging @@ -28,189 +16,6 @@ import pprint import shutil import sys -def get_full_path_to_script(): - return os.path.abspath(__file__) - -def get_cmake_contrib_dir(): - return os.path.dirname(get_full_path_to_script()) - -def get_repo_root_dir(): - r = os.path.dirname(os.path.dirname(get_cmake_contrib_dir())) - assert os.path.isdir(r) - return r - -# These are paths that should be ignored when checking if a folder -# in the ``contrib/cmake`` exists in the root of the repository -verificationExceptions = { - os.path.join(get_repo_root_dir(), 'cmake'), - os.path.join(get_repo_root_dir(), 'cmake', 'modules') -} - -def contribPathToRepoPath(path): - assert path.startswith(get_cmake_contrib_dir()) - stripped = path[len(get_cmake_contrib_dir()) + 1:] # Plus one is to remove leading slash - assert not os.path.isabs(stripped) - logging.debug('stripped:{}'.format(stripped)) - r = os.path.join(get_repo_root_dir(), stripped) - assert os.path.isabs(r) - logging.debug('Converted contrib path "{}" to repo path "{}"'.format(path, r)) - return r - -def verify_mirrored_directory_struture(): - """ - Check that the directories contained in ``contrib/cmake`` exist - in the root of the repo. - """ - for (dirpath, _, _) in os.walk(get_cmake_contrib_dir()): - expectedDir = contribPathToRepoPath(dirpath) - logging.debug('expectedDir:{}'.format(expectedDir)) - if (not (os.path.exists(expectedDir) and os.path.isdir(expectedDir)) and - expectedDir not in verificationExceptions): - logging.error(('Expected to find directory "{}" but it does not exist' - ' or is not a directory').format(expectedDir)) - return 1 - - return 0 - -def mk_sym_link(target, linkName): - logging.info('Making symbolic link target="{}", linkName="{}"'.format(target, linkName)) - if os.path.exists(linkName): - logging.info('Removing existing link "{}"'.format(linkName)) - if not os.path.islink(linkName): - logging.warning('"{}" overwriting file that is not a symlink'.format(linkName)) - delete_path(linkName) - if os.name == 'posix': - os.symlink(target, linkName) - else: - # TODO: Windows does support symlinks but the implementation to do that - # from python is a little complicated so for now lets just copy everyting - logging.warning('Creating symbolic links is not supported. Just making a copy instead') - if os.path.isdir(target): - # Recursively copy directory - shutil.copytree(src=target, dst=linkName, symlinks=False) - else: - # Copy file - assert os.path.isfile(target) - shutil.copy2(src=target, dst=linkName) - -def delete_path(path): - logging.info('Removing "{}"'.format(path)) - if not os.path.exists(path): - logging.warning('"{}" does not exist'.format(path)) - return - if os.path.isdir(path) and not os.path.islink(path): - # FIXME: If we can get symbolic link support on Windows we - # can disallow this completely. - assert os.name == 'nt' - shutil.rmtree(path) - else: - os.remove(path) - -def shouldSkipFile(path): - # Skip this script - if path == get_full_path_to_script(): - return True - # Skip the maintainers file - if path == os.path.join(get_cmake_contrib_dir(), 'maintainers.txt'): - return True - # Skip Vim temporary files - if os.path.basename(path).startswith('.') and path.endswith('.swp'): - return True - return False - - -def create(useHardLinks): - """ - Copy or hard link files in the CMake contrib directory - into the repository where they are intended to live. - - Note that symbolic links for the CMakeLists.txt files - are not appropriate because they won't have the right - file modification time when the files they point to - are modified. This would prevent CMake from correctly - reconfiguring when it detects this is required. - """ - - # Make the ``cmake`` directory a symbolic link. - # We treat this one specially as it is the only directory - # that doesn't already exist in the repository root so - # we can just use a symlink here - linkName = os.path.join(get_repo_root_dir(), 'cmake') - target = os.path.join(get_cmake_contrib_dir(), 'cmake') - specialDir = target - mk_sym_link(target, linkName) - - for (dirPath,_ , fileNames) in os.walk(get_cmake_contrib_dir()): - # Skip the special directory and its children - if dirPath.startswith(specialDir): - logging.info('Skipping directory "{}"'.format(dirPath)) - continue - - for fileName in fileNames: - fileInContrib = os.path.join(dirPath, fileName) - # Skip files - if shouldSkipFile(fileInContrib): - logging.info('Skipping "{}"'.format(fileInContrib)) - continue - fileInRepo = contribPathToRepoPath(fileInContrib) - logging.info('"{}" => "{}"'.format(fileInContrib, fileInRepo)) - if useHardLinks: - if not os.name == 'posix': - logging.error('Hard links are not supported on your platform') - return False - if os.path.exists(fileInRepo): - delete_path(fileInRepo) - os.link(fileInContrib, fileInRepo) - else: - try: - shutil.copy2(src=fileInContrib, dst=fileInRepo) - except shutil.Error as e: - # Can hit this if used created hard links first and then run again without - # wanting hard links - if sys.version_info.major <= 2: - logging.error(e.message) - else: - # Python >= 3 - if isinstance(e, shutil.SameFileError): - logging.error('Trying to copy "{}" to "{}" but they are the same file'.format( - fileInContrib, fileInRepo)) - else: - logging.error(e) - logging.error('You should remove the files using the "remove" mode ' - 'and try to create again. You probably are mixing the ' - 'hard-link and non-hard-link create modes') - return False - return True - -def remove(): - """ - Remove the CMake files from their intended location in - the repository. This is used to remove - the files created by the ``create()`` function. - """ - # This directory is treated specially as it is normally - # a symlink. - linkName = os.path.join(get_repo_root_dir(), 'cmake') - delete_path(linkName) - specialDir = os.path.join(get_cmake_contrib_dir(), 'cmake') - - for (dirPath,_ , fileNames) in os.walk(get_cmake_contrib_dir()): - # Skip the special directory and its children - if dirPath.startswith(specialDir): - logging.info('Skipping directory "{}"'.format(dirPath)) - continue - for fileName in fileNames: - fileInContrib = os.path.join(dirPath, fileName) - # Skip files - if shouldSkipFile(fileInContrib): - logging.info('Skipping "{}"'.format(fileInContrib)) - continue - fileInRepo = contribPathToRepoPath(fileInContrib) - if os.path.exists(fileInRepo): - logging.info('Removing "{}"'.format(fileInRepo)) - delete_path(fileInRepo) - return True - def main(args): logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser(description=__doc__) @@ -233,28 +38,10 @@ def main(args): logLevel = getattr(logging, pargs.log_level.upper(),None) logging.basicConfig(level=logLevel) - - # Before we start make sure we can transplant the CMake files on to - # repository - if verify_mirrored_directory_struture() != 0: - logging.error('"{}" does not mirror "{}"'.format(get_cmake_contrib_dir(), get_repo_root_dir())) - return 1 - - if pargs.mode == "create": - if not create(useHardLinks=pargs.hard_link): - logging.error("Failed to create") - return 1 - elif pargs.mode == "create_hard_link": - if not create(useHardLinks=True): - logging.error("Failed to create_hard_link") - return 1 - elif pargs.mode == "remove": - if not remove(): - logging.error("Failed to remove") - return 1 - else: - logging.error('Unknown mode "{}"'.format(pargs.mode)) - + logging.warning('Use of this script is deprecated. The script will be removed in the future') + logging.warning('Action "{}" ignored'.format(pargs.mode)) + if pargs.hard_link: + logging.warning('Hard link option ignored') return 0 if __name__ == '__main__': From 814fcd6a17e2602ddeb446347d89441c56162402 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Mon, 12 Jun 2017 10:44:19 +0100 Subject: [PATCH 018/159] [CMake] Remove documentation on "Bootstrapping". It is no longer relevant. --- README-CMake.md | 66 ------------------------------------------------- 1 file changed, 66 deletions(-) diff --git a/README-CMake.md b/README-CMake.md index 1b7d89542..7550808fc 100644 --- a/README-CMake.md +++ b/README-CMake.md @@ -33,34 +33,6 @@ git clean -fx src which will remove the generated source files. -### Bootstrapping - -Most of Z3's CMake files do not live in their correct location. Instead those -files live in the ``contrib/cmake`` folder and a script is provided that will -copy (or hard link) the files into their correct location. - -To copy the files run - -``` -python contrib/cmake/bootstrap.py create -``` - -in the root of the repository. Once you have done this you can now build Z3 using CMake. -Make sure you remember to rerun this command if you pull down new code/rebase/change branch so -that the copied CMake files are up to date. - -To remove the copied files run - -``` -python contrib/cmake/bootstrap.py remove -``` - -Note if you plan to do development on Z3 you should read the developer -notes on bootstrapping in this document. - -What follows is a brief walk through of how to build Z3 using some -of the more commonly used CMake generators. - ### Unix Makefiles Run the following in the top level directory of the Z3 repository. @@ -328,44 +300,6 @@ link is not created when building under Windows. These notes are help developers and packagers of Z3. -### Boostrapping the CMake build - -Z3's CMake system is experimental and not officially supported. Consequently -Z3's developers have decided that they do not want the CMake files in the -``src/`` and ``examples/`` folders. Instead the ``contrib/cmake/bootstrap.py`` -script copies or hard links them into the correct locations. For context -on this decision see https://github.com/Z3Prover/z3/pull/461 . - -The ``contrib/cmake/bootstrap.py create`` command just copies over files which makes -development harder because you have to copy your modifications over to the -files in ``contrib/cmake`` for your changes to committed to git. If you are on a UNIX like -platform you can create hard links instead by running - -``` -contrib/cmake/boostrap.py create --hard-link -``` - -Using hard links means that modifying any of the "copied" files also modifies the -file under version control. Using hard links also means that the file modification time -will appear correct (i.e. the hard-linked "copies" have the same file modification time -as the corresponding file under version control) which means CMake will correctly reconfigure -when invoked. This is why using symbolic links is not an option because the file modification -time of a symbolic link is not the same as the file modification of the file being pointed to. - -Unfortunately a downside to using hard links (or just plain copies) is that if -you pull down new code (i.e. ``git pull``) then some of the CMake files under -version control may change but the corresponding hard-linked "copies" will not. - -This mean that (regardless of whether or not you use hard links) every time you -pull down new code or change branch or do an interactive rebase you must run -(with or without ``--hard-link``): - -``` -contrb/cmake/boostrap.py create -``` - -in order to be sure that the copied CMake files are not out of date. - ### Install/Uninstall Install and uninstall targets are supported. Use ``CMAKE_INSTALL_PREFIX`` to From 6bce1732483531e2ca65f34369bb449ba9e9c5fc Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 12 Jun 2017 18:35:02 -0700 Subject: [PATCH 019/159] properly quote symbols #1061 Signed-off-by: Nikolaj Bjorner --- src/cmd_context/basic_cmds.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index 35e157af5..f6eea729f 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -149,7 +149,14 @@ ATOMIC_CMD(get_assignment_cmd, "get-assignment", "retrieve assignment", { first = false; else ctx.regular_stream() << " "; - ctx.regular_stream() << "(" << escaped(name.str().c_str()) << " " << (ctx.m().is_true(val) ? "true" : "false") << ")"; + ctx.regular_stream() << "("; + if (is_smt2_quoted_symbol(name)) { + ctx.regular_stream() << mk_smt2_quoted_symbol(name); + } + else { + ctx.regular_stream() << name; + } + ctx.regular_stream() << " " << (ctx.m().is_true(val) ? "true" : "false") << ")"; } } } From 3a692fe33c2992576ad381d050836a3b0913c996 Mon Sep 17 00:00:00 2001 From: "KangJing Huang (Chaserhkj)" Date: Tue, 13 Jun 2017 00:25:36 -0400 Subject: [PATCH 020/159] Add translate method for FuncDecl in java api --- src/api/java/FuncDecl.java | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/api/java/FuncDecl.java b/src/api/java/FuncDecl.java index 273e853c0..5909540b4 100644 --- a/src/api/java/FuncDecl.java +++ b/src/api/java/FuncDecl.java @@ -1,6 +1,6 @@ /** Copyright (c) 2012-2014 Microsoft Corporation - + Module Name: FuncDecl.java @@ -12,8 +12,8 @@ Author: @author Christoph Wintersteiger (cwinter) 2012-03-15 Notes: - -**/ + +**/ package com.microsoft.z3; @@ -59,6 +59,24 @@ public class FuncDecl extends AST return Native.getFuncDeclId(getContext().nCtx(), getNativeObject()); } + /** + * Translates (copies) the AST to the Context {@code ctx}. + * @param ctx A context + * + * @return A copy of the AST which is associated with {@code ctx} + * @throws Z3Exception on error + **/ + public FuncDecl translate(Context ctx) + { + + if (getContext() == ctx) { + return this; + } else { + return new FuncDecl(ctx, Native.translate(getContext().nCtx(), + getNativeObject(), ctx.nCtx())); + } + } + /** * The arity of the function declaration **/ @@ -68,7 +86,7 @@ public class FuncDecl extends AST } /** - * The size of the domain of the function declaration + * The size of the domain of the function declaration * @see #getArity **/ public int getDomainSize() @@ -324,7 +342,7 @@ public class FuncDecl extends AST } FuncDecl(Context ctx, Symbol name, Sort[] domain, Sort range) - + { super(ctx, Native.mkFuncDecl(ctx.nCtx(), name.getNativeObject(), AST.arrayLength(domain), AST.arrayToNative(domain), @@ -333,7 +351,7 @@ public class FuncDecl extends AST } FuncDecl(Context ctx, String prefix, Sort[] domain, Sort range) - + { super(ctx, Native.mkFreshFuncDecl(ctx.nCtx(), prefix, AST.arrayLength(domain), AST.arrayToNative(domain), @@ -351,7 +369,7 @@ public class FuncDecl extends AST } /** - * Create expression that applies function to arguments. + * Create expression that applies function to arguments. **/ public Expr apply(Expr ... args) { From 5799947183980eb440cfff243ca794e14872ce0b Mon Sep 17 00:00:00 2001 From: "KangJing Huang (Chaserhkj)" Date: Tue, 13 Jun 2017 02:37:41 -0400 Subject: [PATCH 021/159] Fix docstrings for FuncDecl.translate --- src/api/java/FuncDecl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/java/FuncDecl.java b/src/api/java/FuncDecl.java index 5909540b4..8b1ad4b44 100644 --- a/src/api/java/FuncDecl.java +++ b/src/api/java/FuncDecl.java @@ -60,10 +60,10 @@ public class FuncDecl extends AST } /** - * Translates (copies) the AST to the Context {@code ctx}. + * Translates (copies) the function declaration to the Context {@code ctx}. * @param ctx A context * - * @return A copy of the AST which is associated with {@code ctx} + * @return A copy of the function declaration which is associated with {@code ctx} * @throws Z3Exception on error **/ public FuncDecl translate(Context ctx) From a59ee8032c0e6e7483f0b2bdad4b0dbe71ea4d1f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 13 Jun 2017 19:02:59 -0700 Subject: [PATCH 022/159] fix unsoundness bug in axiomatization of str.at. #1067 Signed-off-by: Nikolaj Bjorner --- src/api/dotnet/FuncDecl.cs | 1 - src/smt/smt_conflict_resolution.cpp | 4 +++- src/smt/theory_seq.cpp | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/api/dotnet/FuncDecl.cs b/src/api/dotnet/FuncDecl.cs index 2f5cd0ce8..df90f9cd4 100644 --- a/src/api/dotnet/FuncDecl.cs +++ b/src/api/dotnet/FuncDecl.cs @@ -342,6 +342,5 @@ namespace Microsoft.Z3 Context.CheckContextMatch(args); return Expr.Create(Context, this, args); } - } } diff --git a/src/smt/smt_conflict_resolution.cpp b/src/smt/smt_conflict_resolution.cpp index 8d90f9583..ade667e34 100644 --- a/src/smt/smt_conflict_resolution.cpp +++ b/src/smt/smt_conflict_resolution.cpp @@ -1405,6 +1405,7 @@ namespace smt { switch (js.get_kind()) { case b_justification::CLAUSE: { clause * cls = js.get_clause(); + TRACE("unsat_core_bug", m_ctx.display_clause_detail(tout, cls);); unsigned num_lits = cls->get_num_literals(); unsigned i = 0; if (consequent != false_literal) { @@ -1422,8 +1423,9 @@ namespace smt { process_antecedent_for_unsat_core(~l); } justification * js = cls->get_justification(); - if (js) + if (js) { process_justification_for_unsat_core(js); + } break; } case b_justification::BIN_CLAUSE: diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index 3f8845546..af8b9e395 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -3567,8 +3567,8 @@ void theory_seq::add_at_axiom(expr* e) { add_axiom(~i_ge_0, i_ge_len_s, mk_eq(one, len_e, false)); add_axiom(~i_ge_0, i_ge_len_s, mk_eq(i, len_x, false)); - add_axiom(i_ge_0, mk_eq(s, emp, false)); - add_axiom(~i_ge_len_s, mk_eq(s, emp, false)); + add_axiom(i_ge_0, mk_eq(e, emp, false)); + add_axiom(~i_ge_len_s, mk_eq(e, emp, false)); } /** From c2acbc295774ef2da927a89002fe433138bb29cd Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 13 Jun 2017 19:11:28 -0700 Subject: [PATCH 023/159] port FuncDecl copy to dotnet, continuation of #1073 Signed-off-by: Nikolaj Bjorner --- src/api/dotnet/FuncDecl.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/api/dotnet/FuncDecl.cs b/src/api/dotnet/FuncDecl.cs index df90f9cd4..345019892 100644 --- a/src/api/dotnet/FuncDecl.cs +++ b/src/api/dotnet/FuncDecl.cs @@ -315,6 +315,23 @@ namespace Microsoft.Z3 #endif #endregion + /// + /// Translates (copies) the function declaration to the Context . + /// + /// A context + /// A copy of the function declaration which is associated with + new public FuncDecl Translate(Context ctx) + { + Contract.Requires(ctx != null); + Contract.Ensures(Contract.Result() != null); + + if (ReferenceEquals(Context, ctx)) + return this; + else + return new FuncDecl(ctx, Native.Z3_translate(Context.nCtx, NativeObject, ctx.nCtx)); + } + + /// /// Create expression that applies function to arguments. /// From 8b12cc0bdfc1bee9f5f405ac596309dbbe16d140 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 13 Jun 2017 19:58:55 -0700 Subject: [PATCH 024/159] fix build warning Signed-off-by: Nikolaj Bjorner --- src/cmd_context/cmd_context.cpp | 2 +- src/cmd_context/cmd_context.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index d4273d42d..caafbfb8c 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -325,8 +325,8 @@ cmd_context::cmd_context(bool main_ctx, ast_manager * m, symbol const & l): m_status(UNKNOWN), m_numeral_as_real(false), m_ignore_check(false), - m_exit_on_error(false), m_processing_pareto(false), + m_exit_on_error(false), m_manager(m), m_own_manager(m == 0), m_manager_initialized(false), diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index ed92ab909..b231e3c82 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -159,7 +159,7 @@ protected: bool m_produce_assignments; status m_status; bool m_numeral_as_real; - bool m_ignore_check; // used by the API to disable check-sat() commands when parsing SMT 2.0 files. + bool m_ignore_check; // used by the API to disable check-sat() commands when parsing SMT 2.0 files. bool m_processing_pareto; // used when re-entering check-sat for pareto front. bool m_exit_on_error; From b978f78c21b639bee034693d5bfc627d914e7424 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 13 Jun 2017 20:35:35 -0700 Subject: [PATCH 025/159] add sequence recognizers Signed-off-by: Nikolaj Bjorner --- src/api/dotnet/Expr.cs | 55 +++++++++++++++++++++++++++++++++ src/cmd_context/cmd_context.cpp | 1 + 2 files changed, 56 insertions(+) diff --git a/src/api/dotnet/Expr.cs b/src/api/dotnet/Expr.cs index 23ffe61bd..5e0abcb74 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -811,6 +811,61 @@ namespace Microsoft.Z3 /// the expression should be a string constant, (IsString should be true). public string String { get { return Native.Z3_get_string(Context.nCtx, NativeObject); } } + /// + /// Check whether expression is a concatentation. + /// + /// a Boolean + public bool IsConcat { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_CONCAT; } } + + /// + /// Check whether expression is a prefix. + /// + /// a Boolean + public bool IsPrefix { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_PREFIX; } } + + /// + /// Check whether expression is a suffix. + /// + /// a Boolean + public bool IsSuffix { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_SUFFIX; } } + + /// + /// Check whether expression is a contains. + /// + /// a Boolean + public bool IsContains { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_CONTAINS; } } + + /// + /// Check whether expression is an extract. + /// + /// a Boolean + public bool IsExtract { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_EXTRACT; } } + + /// + /// Check whether expression is a replace. + /// + /// a Boolean + public bool IsReplace { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_REPLACE; } } + + /// + /// Check whether expression is an at. + /// + /// a Boolean + public bool IsAt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_AT; } } + + /// + /// Check whether expression is a sequence length. + /// + /// a Boolean + public bool IsLength { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_LENGTH; } } + + /// + /// Check whether expression is a sequence index. + /// + /// a Boolean + public bool IsIndex { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_INDEX; } } + + #endregion #region Proof Terms diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index caafbfb8c..af16f5796 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -15,6 +15,7 @@ Author: Notes: --*/ + #include #include"tptr.h" #include"cmd_context.h" From c980cfd783fd9ff297e7971b695a2e425b6f7d60 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 13 Jun 2017 20:51:55 -0700 Subject: [PATCH 026/159] add concat recognizer Signed-off-by: Nikolaj Bjorner --- src/api/java/Expr.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index 71a2e3e1e..707f3300d 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -1297,6 +1297,15 @@ public class Expr extends AST return Native.getString(getContext().nCtx(), getNativeObject()); } + /** + * Check whether expression is a concatenation + * @return a boolean + */ + public boolean isConcat() + { + return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_SEQ_CONCAT; + } + /** * Indicates whether the term is a binary equivalence modulo namings. * Remarks: This binary predicate is used in proof terms. It captures From e3f32ca3a8820e4f26615fe366ffc1b96aca9f2a Mon Sep 17 00:00:00 2001 From: "KangJing Huang (Chaserhkj)" Date: Wed, 14 Jun 2017 02:18:21 -0400 Subject: [PATCH 027/159] Fix Z3_PRINT_SMTLIB_FULL not working as expected --- src/api/api_ast.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index 3cec4ec02..7342b3c49 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -821,9 +821,13 @@ extern "C" { RESET_ERROR_CODE(); std::ostringstream buffer; switch (mk_c(c)->get_print_mode()) { - case Z3_PRINT_SMTLIB_FULL: - buffer << mk_pp(to_ast(a), mk_c(c)->m()); + case Z3_PRINT_SMTLIB_FULL: { + params_ref p; + p.set_uint("max_depth", 4294967295u); + p.set_uint("min_alias_size", 4294967295u); + buffer << mk_pp(to_ast(a), mk_c(c)->m(), p); break; + } case Z3_PRINT_LOW_LEVEL: buffer << mk_ll_pp(to_ast(a), mk_c(c)->m()); break; @@ -1066,7 +1070,7 @@ extern "C" { case OP_BIT2BOOL: return Z3_OP_BIT2BOOL; case OP_BSMUL_NO_OVFL: return Z3_OP_BSMUL_NO_OVFL; case OP_BUMUL_NO_OVFL: return Z3_OP_BUMUL_NO_OVFL; - case OP_BSMUL_NO_UDFL: return Z3_OP_BSMUL_NO_UDFL; + case OP_BSMUL_NO_UDFL: return Z3_OP_BSMUL_NO_UDFL; case OP_BSDIV_I: return Z3_OP_BSDIV_I; case OP_BUDIV_I: return Z3_OP_BUDIV_I; case OP_BSREM_I: return Z3_OP_BSREM_I; From d8a02bc0400e08786132779d1c81607cbc2109bb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 14 Jun 2017 13:24:54 +0100 Subject: [PATCH 028/159] Fixed AST translation functions in .NET and Java APIs. Fixes #1073. --- examples/dotnet/Program.cs | 27 +++++++++++++++++++++++++++ examples/java/JavaExample.java | 33 +++++++++++++++++++++++++++++---- src/api/dotnet/AST.cs | 16 ++++++++-------- src/api/dotnet/Expr.cs | 24 +++++++++--------------- src/api/dotnet/FuncDecl.cs | 16 +++++----------- src/api/dotnet/Quantifier.cs | 12 +++++++++++- src/api/dotnet/Sort.cs | 20 +++++++++++++++----- src/api/java/AST.java | 4 +--- src/api/java/Expr.java | 9 +-------- src/api/java/FuncDecl.java | 8 +------- src/api/java/Quantifier.java | 13 +++++++++++++ src/api/java/Sort.java | 13 +++++++++++++ 12 files changed, 133 insertions(+), 62 deletions(-) diff --git a/examples/dotnet/Program.cs b/examples/dotnet/Program.cs index 20bb012b1..64149a553 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -2152,6 +2152,31 @@ namespace test_mapi Console.WriteLine("OK, model: {0}", s.Model.ToString()); } + public static void TranslationExample() + { + Context ctx1 = new Context(); + Context ctx2 = new Context(); + + Sort s1 = ctx1.IntSort; + Sort s2 = ctx2.IntSort; + Sort s3 = s1.Translate(ctx2); + + Console.WriteLine(s1 == s2); + Console.WriteLine(s1.Equals(s2)); + Console.WriteLine(s2.Equals(s3)); + Console.WriteLine(s1.Equals(s3)); + + Expr e1 = ctx1.MkIntConst("e1"); + Expr e2 = ctx2.MkIntConst("e1"); + Expr e3 = e1.Translate(ctx2); + + Console.WriteLine(e1 == e2); + Console.WriteLine(e1.Equals(e2)); + Console.WriteLine(e2.Equals(e3)); + Console.WriteLine(e1.Equals(e3)); + } + + static void Main(string[] args) { try @@ -2225,6 +2250,8 @@ namespace test_mapi QuantifierExample4(ctx); } + TranslationExample(); + Log.Close(); if (Log.isOpen()) Console.WriteLine("Log is still open!"); diff --git a/examples/java/JavaExample.java b/examples/java/JavaExample.java index 5810dab37..25076e27c 100644 --- a/examples/java/JavaExample.java +++ b/examples/java/JavaExample.java @@ -281,7 +281,7 @@ class JavaExample } void disprove(Context ctx, BoolExpr f, boolean useMBQI) - throws TestFailedException + throws TestFailedException { BoolExpr[] a = {}; disprove(ctx, f, useMBQI, a); @@ -2279,6 +2279,29 @@ class JavaExample System.out.println(my); } + public void translationExample() { + Context ctx1 = new Context(); + Context ctx2 = new Context(); + + Sort s1 = ctx1.getIntSort(); + Sort s2 = ctx2.getIntSort(); + Sort s3 = s1.translate(ctx2); + + System.out.println(s1 == s2); + System.out.println(s1.equals(s2)); + System.out.println(s2.equals(s3)); + System.out.println(s1.equals(s3)); + + Expr e1 = ctx1.mkIntConst("e1"); + Expr e2 = ctx2.mkIntConst("e1"); + Expr e3 = e1.translate(ctx2); + + System.out.println(e1 == e2); + System.out.println(e1.equals(e2)); + System.out.println(e2.equals(e3)); + System.out.println(e1.equals(e3)); + } + public static void main(String[] args) { JavaExample p = new JavaExample(); @@ -2300,8 +2323,8 @@ class JavaExample HashMap cfg = new HashMap(); cfg.put("model", "true"); Context ctx = new Context(cfg); - - p.optimizeExample(ctx); + + p.optimizeExample(ctx); p.basicTests(ctx); p.castingTest(ctx); p.sudokuExample(ctx); @@ -2355,7 +2378,9 @@ class JavaExample Context ctx = new Context(cfg); p.quantifierExample3(ctx); p.quantifierExample4(ctx); - } + } + + p.translationExample(); Log.close(); if (Log.isOpen()) diff --git a/src/api/dotnet/AST.cs b/src/api/dotnet/AST.cs index 2ffaaa661..c7ca1851e 100644 --- a/src/api/dotnet/AST.cs +++ b/src/api/dotnet/AST.cs @@ -14,7 +14,7 @@ Author: Christoph Wintersteiger (cwinter) 2012-03-16 Notes: - + --*/ using System; @@ -25,7 +25,7 @@ using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// - /// The abstract syntax tree (AST) class. + /// The abstract syntax tree (AST) class. /// [ContractVerification(true)] public class AST : Z3Object, IComparable @@ -35,7 +35,7 @@ namespace Microsoft.Z3 /// /// An AST /// An AST - /// True if and are from the same context + /// True if and are from the same context /// and represent the same sort; false otherwise. public static bool operator ==(AST a, AST b) { @@ -51,7 +51,7 @@ namespace Microsoft.Z3 /// /// An AST /// An AST - /// True if and are not from the same context + /// True if and are not from the same context /// or represent different sorts; false otherwise. public static bool operator !=(AST a, AST b) { @@ -120,12 +120,12 @@ namespace Microsoft.Z3 if (ReferenceEquals(Context, ctx)) return this; else - return new AST(ctx, Native.Z3_translate(Context.nCtx, NativeObject, ctx.nCtx)); + return Create(ctx, Native.Z3_translate(Context.nCtx, NativeObject, ctx.nCtx)); } /// /// The kind of the AST. - /// + /// public Z3_ast_kind ASTKind { get { return (Z3_ast_kind)Native.Z3_get_ast_kind(Context.nCtx, NativeObject); } @@ -224,10 +224,10 @@ namespace Microsoft.Z3 { Native.Z3_dec_ref(ctx.nCtx, obj); } - }; + }; internal override void IncRef(IntPtr o) - { + { // Console.WriteLine("AST IncRef()"); if (Context == null || o == IntPtr.Zero) return; diff --git a/src/api/dotnet/Expr.cs b/src/api/dotnet/Expr.cs index 5e0abcb74..6c52b83c8 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -163,13 +163,7 @@ namespace Microsoft.Z3 /// A copy of the term which is associated with new public Expr Translate(Context ctx) { - Contract.Requires(ctx != null); - Contract.Ensures(Contract.Result() != null); - - if (ReferenceEquals(Context, ctx)) - return this; - else - return Expr.Create(ctx, Native.Z3_translate(Context.nCtx, NativeObject, ctx.nCtx)); + return (Expr)base.Translate(ctx); } /// @@ -809,7 +803,7 @@ namespace Microsoft.Z3 /// Retrieve string corresponding to string constant. /// /// the expression should be a string constant, (IsString should be true). - public string String { get { return Native.Z3_get_string(Context.nCtx, NativeObject); } } + public string String { get { return Native.Z3_get_string(Context.nCtx, NativeObject); } } /// /// Check whether expression is a concatentation. @@ -828,43 +822,43 @@ namespace Microsoft.Z3 /// /// a Boolean public bool IsSuffix { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_SUFFIX; } } - + /// /// Check whether expression is a contains. /// /// a Boolean public bool IsContains { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_CONTAINS; } } - + /// /// Check whether expression is an extract. /// /// a Boolean public bool IsExtract { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_EXTRACT; } } - + /// /// Check whether expression is a replace. /// /// a Boolean public bool IsReplace { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_REPLACE; } } - + /// /// Check whether expression is an at. /// /// a Boolean - public bool IsAt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_AT; } } + public bool IsAt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_AT; } } /// /// Check whether expression is a sequence length. /// /// a Boolean public bool IsLength { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_LENGTH; } } - + /// /// Check whether expression is a sequence index. /// /// a Boolean public bool IsIndex { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_INDEX; } } - + #endregion diff --git a/src/api/dotnet/FuncDecl.cs b/src/api/dotnet/FuncDecl.cs index 345019892..0587a2276 100644 --- a/src/api/dotnet/FuncDecl.cs +++ b/src/api/dotnet/FuncDecl.cs @@ -14,7 +14,7 @@ Author: Christoph Wintersteiger (cwinter) 2012-03-16 Notes: - + --*/ using System; @@ -23,7 +23,7 @@ using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// - /// Function declarations. + /// Function declarations. /// [ContractVerification(true)] public class FuncDecl : AST @@ -62,7 +62,7 @@ namespace Microsoft.Z3 /// /// A hash code. - /// + /// public override int GetHashCode() { return base.GetHashCode(); @@ -205,7 +205,7 @@ namespace Microsoft.Z3 } /// - /// Function declarations can have Parameters associated with them. + /// Function declarations can have Parameters associated with them. /// public class Parameter { @@ -322,13 +322,7 @@ namespace Microsoft.Z3 /// A copy of the function declaration which is associated with new public FuncDecl Translate(Context ctx) { - Contract.Requires(ctx != null); - Contract.Ensures(Contract.Result() != null); - - if (ReferenceEquals(Context, ctx)) - return this; - else - return new FuncDecl(ctx, Native.Z3_translate(Context.nCtx, NativeObject, ctx.nCtx)); + return (FuncDecl) base.Translate(ctx); } diff --git a/src/api/dotnet/Quantifier.cs b/src/api/dotnet/Quantifier.cs index eb21ed2b9..eca4e3c7e 100644 --- a/src/api/dotnet/Quantifier.cs +++ b/src/api/dotnet/Quantifier.cs @@ -14,7 +14,7 @@ Author: Christoph Wintersteiger (cwinter) 2012-03-19 Notes: - + --*/ using System; @@ -157,6 +157,16 @@ namespace Microsoft.Z3 } } + /// + /// Translates (copies) the quantifier to the Context . + /// + /// A context + /// A copy of the quantifier which is associated with + new public Quantifier Translate(Context ctx) + { + return (Quantifier)base.Translate(ctx); + } + #region Internal [ContractVerification(false)] // F: Clousot ForAll decompilation gets confused below. Setting verification off until I fixed the bug internal Quantifier(Context ctx, bool isForall, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) diff --git a/src/api/dotnet/Sort.cs b/src/api/dotnet/Sort.cs index e1b8ca1b7..e6f195434 100644 --- a/src/api/dotnet/Sort.cs +++ b/src/api/dotnet/Sort.cs @@ -14,7 +14,7 @@ Author: Christoph Wintersteiger (cwinter) 2012-03-15 Notes: - + --*/ using System; @@ -33,7 +33,7 @@ namespace Microsoft.Z3 /// /// A Sort /// A Sort - /// True if and are from the same context + /// True if and are from the same context /// and represent the same sort; false otherwise. public static bool operator ==(Sort a, Sort b) { @@ -49,7 +49,7 @@ namespace Microsoft.Z3 /// /// A Sort /// A Sort - /// True if and are not from the same context + /// True if and are not from the same context /// or represent different sorts; false otherwise. public static bool operator !=(Sort a, Sort b) { @@ -113,10 +113,20 @@ namespace Microsoft.Z3 return Native.Z3_sort_to_string(Context.nCtx, NativeObject); } + /// + /// Translates (copies) the sort to the Context . + /// + /// A context + /// A copy of the sort which is associated with + new public Sort Translate(Context ctx) + { + return (Sort)base.Translate(ctx); + } + #region Internal /// /// Sort constructor - /// + /// internal Sort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } #if DEBUG @@ -154,5 +164,5 @@ namespace Microsoft.Z3 } } #endregion - } + } } diff --git a/src/api/java/AST.java b/src/api/java/AST.java index e1cde837f..350830443 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -87,12 +87,10 @@ public class AST extends Z3Object implements Comparable **/ public AST translate(Context ctx) { - if (getContext() == ctx) { return this; } else { - return new AST(ctx, Native.translate(getContext().nCtx(), - getNativeObject(), ctx.nCtx())); + return create(ctx, Native.translate(getContext().nCtx(), getNativeObject(), ctx.nCtx())); } } diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index 707f3300d..6cabbb1b8 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -194,14 +194,7 @@ public class Expr extends AST **/ public Expr translate(Context ctx) { - if (getContext() == ctx) { - return this; - } else { - return Expr.create( - ctx, - Native.translate(getContext().nCtx(), getNativeObject(), - ctx.nCtx())); - } + return (Expr) super.translate(ctx); } /** diff --git a/src/api/java/FuncDecl.java b/src/api/java/FuncDecl.java index 8b1ad4b44..255bc2c4a 100644 --- a/src/api/java/FuncDecl.java +++ b/src/api/java/FuncDecl.java @@ -68,13 +68,7 @@ public class FuncDecl extends AST **/ public FuncDecl translate(Context ctx) { - - if (getContext() == ctx) { - return this; - } else { - return new FuncDecl(ctx, Native.translate(getContext().nCtx(), - getNativeObject(), ctx.nCtx())); - } + return (FuncDecl) super.translate(ctx); } /** diff --git a/src/api/java/Quantifier.java b/src/api/java/Quantifier.java index bc2537107..ce2adce21 100644 --- a/src/api/java/Quantifier.java +++ b/src/api/java/Quantifier.java @@ -145,6 +145,19 @@ public class Quantifier extends BoolExpr .nCtx(), getNativeObject())); } + /** + * Translates (copies) the quantifier to the Context {@code ctx}. + * + * @param ctx A context + * + * @return A copy of the quantifier which is associated with {@code ctx} + * @throws Z3Exception on error + **/ + public Quantifier translate(Context ctx) + { + return (Quantifier) super.translate(ctx); + } + /** * Create a quantified expression. * diff --git a/src/api/java/Sort.java b/src/api/java/Sort.java index 0763a69a3..e7a186ad2 100644 --- a/src/api/java/Sort.java +++ b/src/api/java/Sort.java @@ -87,6 +87,19 @@ public class Sort extends AST return Native.sortToString(getContext().nCtx(), getNativeObject()); } + /** + * Translates (copies) the sort to the Context {@code ctx}. + * + * @param ctx A context + * + * @return A copy of the sort which is associated with {@code ctx} + * @throws Z3Exception on error + **/ + public Sort translate(Context ctx) + { + return (Sort) super.translate(ctx); + } + /** * Sort constructor **/ From 8ac43c981a5e88432c0e0127e292ad859fb438f8 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 14 Jun 2017 21:40:16 -0700 Subject: [PATCH 029/159] use less memory #1078 --- src/tactic/bv/bv_bounds_tactic.cpp | 78 ++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/tactic/bv/bv_bounds_tactic.cpp b/src/tactic/bv/bv_bounds_tactic.cpp index 1b324b2eb..69575b2dc 100644 --- a/src/tactic/bv/bv_bounds_tactic.cpp +++ b/src/tactic/bv/bv_bounds_tactic.cpp @@ -234,6 +234,7 @@ class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier { return false; } +#if 0 expr_set* get_expr_vars(expr* t) { unsigned id = t->get_id(); m_expr_vars.reserve(id + 1); @@ -259,7 +260,9 @@ class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier { } return set; } +#endif +#if 0 expr_cnt* get_expr_bounds(expr* t) { unsigned id = t->get_id(); m_bound_exprs.reserve(id + 1); @@ -288,6 +291,7 @@ class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier { } return set; } +#endifx public: bv_bounds_simplifier(ast_manager& m, params_ref const& p) : m(m), m_params(p), m_bv(m) { @@ -392,17 +396,86 @@ public: return result != 0; } + // check if t contains v + ptr_vector todo; + bool contains(expr* t, expr* v) { + ast_fast_mark1 mark; + todo.push_back(t); + while (!todo.empty()) { + t = todo.back(); + todo.pop_back(); + if (mark.is_marked(t)) { + continue; + } + if (t == v) { + todo.reset(); + return true; + } + mark.mark(t); + + if (!is_app(t)) { + continue; + } + app* a = to_app(t); + todo.append(a->get_num_args(), a->get_args()); + } + return false; + } + + bool contains_bound(expr* t) { + ast_fast_mark1 mark1; + ast_fast_mark2 mark2; + + todo.push_back(t); + while (!todo.empty()) { + t = todo.back(); + todo.pop_back(); + if (mark1.is_marked(t)) { + continue; + } + mark1.mark(t); + + if (!is_app(t)) { + continue; + } + interval b; + expr* e; + if (is_bound(t, e, b)) { + if (mark2.is_marked(e)) { + todo.reset(); + return true; + } + mark2.mark(e); + if (m_bound.contains(e)) { + todo.reset(); + return true; + } + } + + app* a = to_app(t); + todo.append(a->get_num_args(), a->get_args()); + } + return false; + } + virtual bool may_simplify(expr* t) { if (m_bv.is_numeral(t)) return false; while (m.is_not(t, t)); + for (auto & v : m_bound) { + if (contains(t, v.m_key)) return true; + } + +#if 0 expr_set* used_exprs = get_expr_vars(t); for (map::iterator I = m_bound.begin(), E = m_bound.end(); I != E; ++I) { + if (contains(t, I->m_key)) return true; if (I->m_value.is_singleton() && used_exprs->contains(I->m_key)) return true; } +#endif expr* t1; interval b; @@ -411,11 +484,16 @@ public: return b.is_full() || m_bound.contains(t1); } + if (contains_bound(t)) { + return true; + } +#if 0 expr_cnt* bounds = get_expr_bounds(t); for (expr_cnt::iterator I = bounds->begin(), E = bounds->end(); I != E; ++I) { if (I->m_value > 1 || m_bound.contains(I->m_key)) return true; } +#endif return false; } From d3320f8b8143c64badc1a291fd210bb4aef96693 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 14 Jun 2017 21:48:19 -0700 Subject: [PATCH 030/159] fix build Signed-off-by: Nikolaj Bjorner --- src/tactic/bv/bv_bounds_tactic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/bv/bv_bounds_tactic.cpp b/src/tactic/bv/bv_bounds_tactic.cpp index 69575b2dc..94c9935b9 100644 --- a/src/tactic/bv/bv_bounds_tactic.cpp +++ b/src/tactic/bv/bv_bounds_tactic.cpp @@ -291,7 +291,7 @@ class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier { } return set; } -#endifx +#endif public: bv_bounds_simplifier(ast_manager& m, params_ref const& p) : m(m), m_params(p), m_bv(m) { From 5be3e959ab66b8d97cc1a53d12cd10077ed6ff6f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 15 Jun 2017 20:46:47 -0700 Subject: [PATCH 031/159] address issues raised in #998 Signed-off-by: Nikolaj Bjorner --- src/smt/smt_context.h | 4 +++ src/smt/theory_seq.cpp | 57 ++++++++++++++++++++++++++++++++++++++++-- src/smt/theory_seq.h | 5 ++-- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index 9c70f5999..17c3b1b88 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -980,6 +980,10 @@ namespace smt { void push_eq(enode * lhs, enode * rhs, eq_justification const & js) { SASSERT(lhs != rhs); + { + seq_util u(get_manager()); + SASSERT(!u.is_re(lhs->get_owner())); + } m_eq_propagation_queue.push_back(new_eq(lhs, rhs, js)); } diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index af8b9e395..da275de24 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -2176,8 +2176,59 @@ bool theory_seq::simplify_and_solve_eqs() { return m_new_propagation || ctx.inconsistent(); } -void theory_seq::internalize_eq_eh(app * atom, bool_var v) {} +void theory_seq::internalize_eq_eh(app * atom, bool_var v) { +} +bool theory_seq::internalize_atom(app* a, bool) { + context & ctx = get_context(); + bool_var bv = ctx.mk_bool_var(a); + ctx.set_var_theory(bv, get_id()); + ctx.mark_as_relevant(bv); + + expr* e1, *e2; + if (m_util.str.is_in_re(a, e1, e2)) { + return internalize_term(to_app(e1)) && internalize_re(e2); + } + if (m_util.str.is_contains(a, e1, e2) || + m_util.str.is_prefix(a, e1, e2) || + m_util.str.is_suffix(a, e1, e2)) { + return internalize_term(to_app(e1)) && internalize_term(to_app(e2)); + } + if (is_accept(a) || is_reject(a) || is_skolem(m_eq, a) || is_step(a) || is_skolem(symbol("seq.is_digit"), a)) { + return true; + } + UNREACHABLE(); + return internalize_term(a); +} + +bool theory_seq::internalize_re(expr* e) { + expr* e1, *e2; + unsigned lc; + if (m_util.re.is_to_re(e, e1)) { + return internalize_term(to_app(e1)); + } + if (m_util.re.is_star(e, e1) || + m_util.re.is_plus(e, e1) || + m_util.re.is_opt(e, e1) || + m_util.re.is_loop(e, e1, lc) || + m_util.re.is_complement(e, e1)) { + return internalize_re(e1); + } + if (m_util.re.is_union(e, e1, e2) || + m_util.re.is_intersection(e, e1, e2) || + m_util.re.is_concat(e, e1, e2)) { + return internalize_re(e1) && internalize_re(e2); + } + if (m_util.re.is_full(e) || + m_util.re.is_empty(e)) { + return true; + } + if (m_util.re.is_range(e, e1, e2)) { + return internalize_term(to_app(e1)) && internalize_term(to_app(e2)); + } + UNREACHABLE(); + return internalize_term(to_app(e)); +} bool theory_seq::internalize_term(app* term) { context & ctx = get_context(); @@ -3875,7 +3926,9 @@ void theory_seq::new_eq_eh(dependency* deps, enode* n1, enode* n2) { enforce_length_coherence(n1, n2); } else if (n1 != n2 && m_util.is_re(n1->get_owner())) { - warning_msg("equality between regular expressions is not yet supported"); + // ignore + UNREACHABLE(); + // eautomaton* a1 = get_automaton(n1->get_owner()); // eautomaton* a2 = get_automaton(n2->get_owner()); // eautomaton* b1 = mk_difference(*a1, *a2); diff --git a/src/smt/theory_seq.h b/src/smt/theory_seq.h index e145d3077..5fd31e2ca 100644 --- a/src/smt/theory_seq.h +++ b/src/smt/theory_seq.h @@ -341,8 +341,8 @@ namespace smt { virtual void init(context* ctx); virtual final_check_status final_check_eh(); - virtual bool internalize_atom(app* atom, bool) { return internalize_term(atom); } - virtual bool internalize_term(app*); + virtual bool internalize_atom(app* atom, bool); + virtual bool internalize_term(app*); virtual void internalize_eq_eh(app * atom, bool_var v); virtual void new_eq_eh(theory_var, theory_var); virtual void new_diseq_eh(theory_var, theory_var); @@ -387,6 +387,7 @@ namespace smt { vector const& ll, vector const& rl); bool set_empty(expr* x); bool is_complex(eq const& e); + bool internalize_re(expr* e); bool check_extensionality(); bool check_contains(); From e67572ffa6f9c72d8ff85864c33d26cef16b50a2 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 15 Jun 2017 20:47:59 -0700 Subject: [PATCH 032/159] address issues raised in #998 Signed-off-by: Nikolaj Bjorner --- src/smt/smt_context.h | 4 ---- src/smt/theory_seq.cpp | 2 -- 2 files changed, 6 deletions(-) diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index 17c3b1b88..9c70f5999 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -980,10 +980,6 @@ namespace smt { void push_eq(enode * lhs, enode * rhs, eq_justification const & js) { SASSERT(lhs != rhs); - { - seq_util u(get_manager()); - SASSERT(!u.is_re(lhs->get_owner())); - } m_eq_propagation_queue.push_back(new_eq(lhs, rhs, js)); } diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index da275de24..ec22e8520 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -3927,8 +3927,6 @@ void theory_seq::new_eq_eh(dependency* deps, enode* n1, enode* n2) { } else if (n1 != n2 && m_util.is_re(n1->get_owner())) { // ignore - UNREACHABLE(); - // eautomaton* a1 = get_automaton(n1->get_owner()); // eautomaton* a2 = get_automaton(n2->get_owner()); // eautomaton* b1 = mk_difference(*a1, *a2); From 02161f2ff7438d7b293a194675e1fa5fdbedcb7c Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 15 Jun 2017 21:13:25 -0700 Subject: [PATCH 033/159] revert internalize logic for re until debugged Signed-off-by: Nikolaj Bjorner --- src/smt/theory_seq.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index ec22e8520..c98040c17 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -2180,6 +2180,8 @@ void theory_seq::internalize_eq_eh(app * atom, bool_var v) { } bool theory_seq::internalize_atom(app* a, bool) { + return internalize_term(a); +#if 0 context & ctx = get_context(); bool_var bv = ctx.mk_bool_var(a); ctx.set_var_theory(bv, get_id()); @@ -2199,11 +2201,12 @@ bool theory_seq::internalize_atom(app* a, bool) { } UNREACHABLE(); return internalize_term(a); +#endif } bool theory_seq::internalize_re(expr* e) { expr* e1, *e2; - unsigned lc; + unsigned lc, uc; if (m_util.re.is_to_re(e, e1)) { return internalize_term(to_app(e1)); } @@ -2211,6 +2214,7 @@ bool theory_seq::internalize_re(expr* e) { m_util.re.is_plus(e, e1) || m_util.re.is_opt(e, e1) || m_util.re.is_loop(e, e1, lc) || + m_util.re.is_loop(e, e1, lc, uc) || m_util.re.is_complement(e, e1)) { return internalize_re(e1); } @@ -3013,6 +3017,7 @@ void theory_seq::deque_axiom(expr* n) { add_length_axiom(n); } else if (m_util.str.is_empty(n) && !has_length(n) && !m_length.empty()) { + ensure_enode(n); enforce_length(get_context().get_enode(n)); } else if (m_util.str.is_index(n)) { @@ -4046,7 +4051,7 @@ void theory_seq::relevant_eh(app* n) { } expr* arg; - if (m_util.str.is_length(n, arg) && !has_length(arg)) { + if (m_util.str.is_length(n, arg) && !has_length(arg) && get_context().e_internalized(arg)) { enforce_length(get_context().get_enode(arg)); } } From e547000bcfd45b62ac33512560212370c0712f52 Mon Sep 17 00:00:00 2001 From: Dennis Yurichev Date: Mon, 19 Jun 2017 13:52:30 +0300 Subject: [PATCH 034/159] typo --- src/api/python/z3/z3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/z3/z3.py b/src/api/python/z3/z3.py index 84a80ddf7..4234439d0 100644 --- a/src/api/python/z3/z3.py +++ b/src/api/python/z3/z3.py @@ -314,7 +314,7 @@ class AstRef(Z3PPObject): raise Z3Exception("Symbolic expressions cannot be cast to concrete Boolean values.") def sexpr(self): - """Return an string representing the AST node in s-expression notation. + """Return a string representing the AST node in s-expression notation. >>> x = Int('x') >>> ((x + 1)*x).sexpr() From 894c60bdf90841c2af9c73897232027e9a94ead9 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 19 Jun 2017 18:22:30 -0500 Subject: [PATCH 035/159] fix bug in qe-lite reported in #1086: bookkeeping of unconstrained variables only works for quantifier-free formulas Signed-off-by: Nikolaj Bjorner --- src/api/api_ast.cpp | 1 + src/qe/qe_lite.cpp | 7 ++++++- src/smt/theory_seq.cpp | 8 ++++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index 7342b3c49..d34cad2f4 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -558,6 +558,7 @@ extern "C" { Z3_TRY; LOG_Z3_get_sort(c, a); RESET_ERROR_CODE(); + CHECK_IS_EXPR(a, 0); Z3_sort r = of_sort(mk_c(c)->m().get_sort(to_expr(a))); RETURN_Z3(r); Z3_CATCH_RETURN(0); diff --git a/src/qe/qe_lite.cpp b/src/qe/qe_lite.cpp index eccc2d0c7..0e7db9971 100644 --- a/src/qe/qe_lite.cpp +++ b/src/qe/qe_lite.cpp @@ -1491,8 +1491,10 @@ namespace fm { unsigned sz = g.size(); for (unsigned i = 0; i < sz; i++) { expr * f = g[i]; - if (is_occ(f)) + if (is_occ(f)) { + TRACE("qe_lite", tout << "OCC: " << mk_ismt2_pp(f, m) << "\n";); continue; + } TRACE("qe_lite", tout << "not OCC:\n" << mk_ismt2_pp(f, m) << "\n";); quick_for_each_expr(proc, visited, f); } @@ -2221,6 +2223,9 @@ namespace fm { void operator()(expr_ref_vector& fmls) { init(fmls); init_use_list(fmls); + for (auto & f : fmls) { + if (has_quantifiers(f)) return; + } if (m_inconsistent) { m_new_fmls.reset(); m_new_fmls.push_back(m.mk_false()); diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index c98040c17..3b70e1426 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -2180,8 +2180,12 @@ void theory_seq::internalize_eq_eh(app * atom, bool_var v) { } bool theory_seq::internalize_atom(app* a, bool) { - return internalize_term(a); #if 0 + return internalize_term(a); +#else + if (is_skolem(m_eq, a)) { + return internalize_term(a); + } context & ctx = get_context(); bool_var bv = ctx.mk_bool_var(a); ctx.set_var_theory(bv, get_id()); @@ -2196,7 +2200,7 @@ bool theory_seq::internalize_atom(app* a, bool) { m_util.str.is_suffix(a, e1, e2)) { return internalize_term(to_app(e1)) && internalize_term(to_app(e2)); } - if (is_accept(a) || is_reject(a) || is_skolem(m_eq, a) || is_step(a) || is_skolem(symbol("seq.is_digit"), a)) { + if (is_accept(a) || is_reject(a) || is_step(a) || is_skolem(symbol("seq.is_digit"), a)) { return true; } UNREACHABLE(); From f375016a11cd97d64de8ed35bd15def6aec4a162 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 19 Jun 2017 18:23:27 -0500 Subject: [PATCH 036/159] disable tweak to seq until there are cycles to test further Signed-off-by: Nikolaj Bjorner --- src/smt/theory_seq.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index 3b70e1426..4dfff21c2 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -2180,7 +2180,7 @@ void theory_seq::internalize_eq_eh(app * atom, bool_var v) { } bool theory_seq::internalize_atom(app* a, bool) { -#if 0 +#if 1 return internalize_term(a); #else if (is_skolem(m_eq, a)) { From 7b976883020cdf23e0181369744a5f69dbdf4d85 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 20 Jun 2017 14:36:40 +0100 Subject: [PATCH 037/159] Whitespace, typo. --- src/cmd_context/basic_cmds.cpp | 106 ++++++++++++++++----------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index f6eea729f..563d44afa 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -39,7 +39,7 @@ class help_cmd : public cmd { ctx.regular_stream() << " (" << s; if (usage) ctx.regular_stream() << " " << escaped(usage, true) << ")\n"; - else + else ctx.regular_stream() << ")\n"; if (descr) { ctx.regular_stream() << " " << escaped(descr, true, 4) << "\n"; @@ -62,7 +62,7 @@ public: } m_cmds.push_back(s); } - + typedef std::pair named_cmd; struct named_cmd_lt { bool operator()(named_cmd const & c1, named_cmd const & c2) const { return c1.first.str() < c2.first.str(); } @@ -104,14 +104,14 @@ class get_model_cmd : public cmd { unsigned m_index; public: get_model_cmd(): cmd("get-model"), m_index(0) {} - virtual char const * get_usage() const { return "[]"; } - virtual char const * get_descr(cmd_context & ctx) const { - return "retrieve model for the last check-sat command.\nSupply optional index if retrieving a model corresponding to a box optimization objective"; + virtual char const * get_usage() const { return "[]"; } + virtual char const * get_descr(cmd_context & ctx) const { + return "retrieve model for the last check-sat command.\nSupply optional index if retrieving a model corresponding to a box optimization objective"; } - virtual unsigned get_arity() const { return VAR_ARITY; } + virtual unsigned get_arity() const { return VAR_ARITY; } virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_UINT; } - virtual void set_next_arg(cmd_context & ctx, unsigned index) { m_index = index; } - virtual void execute(cmd_context & ctx) { + virtual void set_next_arg(cmd_context & ctx, unsigned index) { m_index = index; } + virtual void execute(cmd_context & ctx) { if (!ctx.is_model_available() || ctx.get_check_sat_result() == 0) throw cmd_exception("model is not available"); model_ref m; @@ -122,7 +122,7 @@ public: ctx.get_check_sat_result()->get_model(m); } ctx.display_model(m); - } + } virtual void reset(cmd_context& ctx) { m_index = 0; } @@ -167,11 +167,11 @@ class cmd_is_declared : public ast_smt_pp::is_declared { cmd_context& m_ctx; public: cmd_is_declared(cmd_context& ctx): m_ctx(ctx) {} - - virtual bool operator()(func_decl* d) const { + + virtual bool operator()(func_decl* d) const { return m_ctx.is_func_decl(d->get_name()); } - virtual bool operator()(sort* s) const { + virtual bool operator()(sort* s) const { return m_ctx.is_sort_decl(s->get_name()); } }; @@ -189,13 +189,13 @@ ATOMIC_CMD(get_proof_cmd, "get-proof", "retrieve proof", { if (ctx.well_sorted_check_enabled() && !is_well_sorted(ctx.m(), pr)) { throw cmd_exception("proof is not well sorted"); } - + pp_params params; if (params.pretty_proof()) { ctx.regular_stream() << mk_pp(pr, ctx.m()) << std::endl; } else { - // TODO: reimplement a new SMT2 pretty printer + // TODO: reimplement a new SMT2 pretty printer ast_smt_pp pp(ctx.m()); cmd_is_declared isd(ctx); pp.set_is_declared(&isd); @@ -206,19 +206,19 @@ ATOMIC_CMD(get_proof_cmd, "get-proof", "retrieve proof", { }); static void print_core(cmd_context& ctx) { - ptr_vector core; - ctx.get_check_sat_result()->get_unsat_core(core); - ctx.regular_stream() << "("; - ptr_vector::const_iterator it = core.begin(); - ptr_vector::const_iterator end = core.end(); - for (bool first = true; it != end; ++it) { - if (first) - first = false; - else - ctx.regular_stream() << " "; - ctx.regular_stream() << mk_ismt2_pp(*it, ctx.m()); - } - ctx.regular_stream() << ")" << std::endl; + ptr_vector core; + ctx.get_check_sat_result()->get_unsat_core(core); + ctx.regular_stream() << "("; + ptr_vector::const_iterator it = core.begin(); + ptr_vector::const_iterator end = core.end(); + for (bool first = true; it != end; ++it) { + if (first) + first = false; + else + ctx.regular_stream() << " "; + ctx.regular_stream() << mk_ismt2_pp(*it, ctx.m()); + } + ctx.regular_stream() << ")" << std::endl; } ATOMIC_CMD(get_unsat_core_cmd, "get-unsat-core", "retrieve unsat core", { @@ -260,7 +260,7 @@ ATOMIC_CMD(get_assertions_cmd, "get-assertions", "retrieve asserted terms when i ATOMIC_CMD(reset_assertions_cmd, "reset-assertions", "reset all asserted formulas (but retain definitions and declarations)", ctx.reset_assertions(); ctx.print_success();); -UNARY_CMD(set_logic_cmd, "set-logic", "", "set the background logic.", CPK_SYMBOL, symbol const &, +UNARY_CMD(set_logic_cmd, "set-logic", "", "set the background logic.", CPK_SYMBOL, symbol const &, if (ctx.set_logic(arg)) ctx.print_success(); else { @@ -269,9 +269,9 @@ UNARY_CMD(set_logic_cmd, "set-logic", "", "set the background logic.", C } ); -UNARY_CMD(pp_cmd, "display", "", "display the given term.", CPK_EXPR, expr *, { +UNARY_CMD(pp_cmd, "display", "", "display the given term.", CPK_EXPR, expr *, { ctx.display(ctx.regular_stream(), arg); - ctx.regular_stream() << std::endl; + ctx.regular_stream() << std::endl; }); UNARY_CMD(echo_cmd, "echo", "", "display the given string", CPK_STRING, char const *, ctx.regular_stream() << "\"" << arg << "\"" << std::endl;); @@ -305,18 +305,18 @@ protected: symbol m_reproducible_resource_limit; bool is_builtin_option(symbol const & s) const { - return - s == m_print_success || s == m_print_warning || s == m_expand_definitions || + return + s == m_print_success || s == m_print_warning || s == m_expand_definitions || s == m_interactive_mode || s == m_produce_proofs || s == m_produce_unsat_cores || s == m_produce_unsat_assumptions || s == m_produce_models || s == m_produce_assignments || s == m_produce_interpolants || - s == m_regular_output_channel || s == m_diagnostic_output_channel || + s == m_regular_output_channel || s == m_diagnostic_output_channel || s == m_random_seed || s == m_verbosity || s == m_global_decls || s == m_global_declarations || s == m_produce_assertions || s == m_reproducible_resource_limit; } public: set_get_option_cmd(char const * name): - cmd(name), + cmd(name), m_true("true"), m_false("false"), m_print_success(":print-success"), @@ -348,7 +348,7 @@ public: class set_option_cmd : public set_get_option_cmd { bool m_unsupported; symbol m_option; - + bool to_bool(symbol const & value) const { if (value != m_true && value != m_false) throw cmd_exception("invalid option value, true/false expected"); @@ -369,7 +369,7 @@ class set_option_cmd : public set_get_option_cmd { throw cmd_exception(msg); } } - + void set_param(cmd_context & ctx, char const * value) { try { gparams::set(m_option, value); @@ -466,11 +466,11 @@ public: virtual void prepare(cmd_context & ctx) { m_unsupported = false; m_option = symbol::null; } - virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { + virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return m_option == symbol::null ? CPK_KEYWORD : CPK_OPTION_VALUE; } - virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { + virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { if (m_option == symbol::null) { m_option = opt; } @@ -525,7 +525,7 @@ class get_option_cmd : public set_get_option_cmd { static void print_bool(cmd_context & ctx, bool b) { ctx.regular_stream() << (b ? "true" : "false") << std::endl; } - + static void print_unsigned(cmd_context & ctx, unsigned v) { ctx.regular_stream() << v << std::endl; } @@ -542,11 +542,11 @@ public: virtual char const * get_descr(cmd_context & ctx) const { return "get configuration option."; } virtual unsigned get_arity() const { return 1; } virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_KEYWORD; } - virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { + virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { if (opt == m_print_success) { - print_bool(ctx, ctx.print_success_enabled()); + print_bool(ctx, ctx.print_success_enabled()); } - // TODO: + // TODO: // else if (opt == m_print_warning) { // print_bool(ctx, ); // } @@ -636,7 +636,7 @@ public: virtual char const * get_descr(cmd_context & ctx) const { return "get information."; } virtual unsigned get_arity() const { return 1; } virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_KEYWORD; } - virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { + virtual void set_next_arg(cmd_context & ctx, symbol const & opt) { if (opt == m_error_behavior) { if (ctx.exit_on_error()) ctx.regular_stream() << "(:error-behavior immediate-exit)" << std::endl; @@ -692,12 +692,12 @@ public: virtual char const * get_descr(cmd_context & ctx) const { return "set information."; } virtual unsigned get_arity() const { return 2; } virtual void prepare(cmd_context & ctx) { m_info = symbol::null; } - virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { - return m_info == symbol::null ? CPK_KEYWORD : CPK_OPTION_VALUE; + virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { + return m_info == symbol::null ? CPK_KEYWORD : CPK_OPTION_VALUE; } virtual void set_next_arg(cmd_context & ctx, rational const & val) {} virtual void set_next_arg(cmd_context & ctx, char const * val) {} - virtual void set_next_arg(cmd_context & ctx, symbol const & s) { + virtual void set_next_arg(cmd_context & ctx, symbol const & s) { if (m_info == symbol::null) { m_info = s; } @@ -745,7 +745,7 @@ public: virtual char const * get_descr(cmd_context & ctx) const { return "declare a new array map operator with name using the given function declaration.\n ::= \n | ( (*) )\n | ((_ +) (*) )\nThe last two cases are used to disumbiguate between declarations with the same name and/or select (indexed) builtin declarations.\nFor more details about the the array map operator, see 'Generalized and Efficient Array Decision Procedures' (FMCAD 2009).\nExample: (declare-map set-union (Int) (or (Bool Bool) Bool))\nDeclares a new function (declare-fun set-union ((Array Int Bool) (Array Int Bool)) (Array Int Bool)).\nThe instance of the map axiom for this new declaration is:\n(forall ((a1 (Array Int Bool)) (a2 (Array Int Bool)) (i Int)) (= (select (set-union a1 a2) i) (or (select a1 i) (select a2 i))))"; } virtual unsigned get_arity() const { return 3; } virtual void prepare(cmd_context & ctx) { m_name = symbol::null; m_domain.reset(); } - virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { + virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { if (m_name == symbol::null) return CPK_SYMBOL; if (m_domain.empty()) return CPK_SORT_LIST; return CPK_FUNC_DECL; @@ -756,10 +756,10 @@ public: throw cmd_exception("invalid map declaration, empty sort list"); m_domain.append(num, slist); } - virtual void set_next_arg(cmd_context & ctx, func_decl * f) { - m_f = f; - if (m_f->get_arity() == 0) - throw cmd_exception("invalid map declaration, function declaration must have arity > 0"); + virtual void set_next_arg(cmd_context & ctx, func_decl * f) { + m_f = f; + if (m_f->get_arity() == 0) + throw cmd_exception("invalid map declaration, function declaration must have arity > 0"); } virtual void reset(cmd_context & ctx) { m_array_fid = null_family_id; @@ -798,7 +798,7 @@ public: virtual char const * get_descr(cmd_context & ctx) const { return "retrieve consequences that fix values for supplied variables"; } virtual unsigned get_arity() const { return 2; } virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_EXPR_LIST; } - virtual void set_next_arg(cmd_context & ctx, unsigned num, expr * const * tlist) { + virtual void set_next_arg(cmd_context & ctx, unsigned num, expr * const * tlist) { if (m_count == 0) { m_assumptions.append(num, tlist); ++m_count; @@ -858,7 +858,7 @@ void install_basic_cmds(cmd_context & ctx) { ctx.insert(alloc(builtin_cmd, "declare-fun", " (*) ", "declare a new function/constant.")); ctx.insert(alloc(builtin_cmd, "declare-const", " ", "declare a new constant.")); ctx.insert(alloc(builtin_cmd, "declare-datatypes", "(*) (+)", "declare mutually recursive datatypes.\n ::= ( +)\n ::= ( *)\n ::= ( )\nexample: (declare-datatypes (T) ((BinTree (leaf (value T)) (node (left BinTree) (right BinTree)))))")); - ctx.insert(alloc(builtin_cmd, "check-sat-asuming", "( hprop_literali* )", "check sat assuming a collection of literals")); + ctx.insert(alloc(builtin_cmd, "check-sat-assuming", "( hprop_literali* )", "check sat assuming a collection of literals")); ctx.insert(alloc(get_unsat_assumptions_cmd)); ctx.insert(alloc(reset_assertions_cmd)); From 054e139c0d9fded534ae8ef3596b279bc25d9f7b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 20 Jun 2017 14:37:26 +0100 Subject: [PATCH 038/159] Whitespace --- src/parsers/smt2/smt2scanner.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/parsers/smt2/smt2scanner.cpp b/src/parsers/smt2/smt2scanner.cpp index fb2f9f34a..1763a4fa5 100644 --- a/src/parsers/smt2/smt2scanner.cpp +++ b/src/parsers/smt2/smt2scanner.cpp @@ -23,7 +23,7 @@ namespace smt2 { void scanner::next() { if (m_cache_input) - m_cache.push_back(m_curr); + m_cache.push_back(m_curr); SASSERT(!m_at_eof); if (m_interactive) { m_curr = m_stream.get(); @@ -293,11 +293,11 @@ namespace smt2 { } scanner::token scanner::scan() { - while (true) { + while (true) { signed char c = curr(); m_pos = m_spos; - if (m_at_eof) + if (m_at_eof) return EOF_TOKEN; switch (m_normalized[(unsigned char) c]) { From ab21caf55f52928b1a3cbaf927bcdd6fd73d92bd Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 20 Jun 2017 14:39:22 +0100 Subject: [PATCH 039/159] Reverted fix for quoted echo strings when smtlib2_compliant=false. Kindly reported by Armael Gueneau. Fixes #1062. --- src/cmd_context/basic_cmds.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index 563d44afa..e915b7b4e 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -274,7 +274,10 @@ UNARY_CMD(pp_cmd, "display", "", "display the given term.", CPK_EXPR, expr ctx.regular_stream() << std::endl; }); -UNARY_CMD(echo_cmd, "echo", "", "display the given string", CPK_STRING, char const *, ctx.regular_stream() << "\"" << arg << "\"" << std::endl;); +UNARY_CMD(pp_cmd, "display", "", "display the given term.", CPK_EXPR, expr *, { + ctx.display(ctx.regular_stream(), arg); + ctx.regular_stream() << std::endl; +}); class set_get_option_cmd : public cmd { From a0b25147d9a1ead8bc0c5949a04ff6ffef67be93 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 20 Jun 2017 14:48:03 +0100 Subject: [PATCH 040/159] Fix for the fix for #1062. --- src/cmd_context/basic_cmds.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index e915b7b4e..ea6d1c232 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -274,10 +274,9 @@ UNARY_CMD(pp_cmd, "display", "", "display the given term.", CPK_EXPR, expr ctx.regular_stream() << std::endl; }); -UNARY_CMD(pp_cmd, "display", "", "display the given term.", CPK_EXPR, expr *, { - ctx.display(ctx.regular_stream(), arg); - ctx.regular_stream() << std::endl; -}); +UNARY_CMD(echo_cmd, "echo", "", "display the given string", CPK_STRING, char const *, + bool smt2c = ctx.params().m_smtlib2_compliant; + ctx.regular_stream() << (smt2c ? "\"" : "") << arg << (smt2c ? "\"" : "") << std::endl;); class set_get_option_cmd : public cmd { From ee2fc41626d61d48afea8b3e14e2fe7169f6fc35 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 20 Jun 2017 15:17:49 +0100 Subject: [PATCH 041/159] Kick CI From 237e6dcd3f06e9804d5f1b876a9c79633a52447a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 20 Jun 2017 17:21:24 +0100 Subject: [PATCH 042/159] Kick CI From 78e8e8b89345417fd1209eee3c3b87504e34ae12 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 20 Jun 2017 18:06:18 +0100 Subject: [PATCH 043/159] Kick CI From 0fa6274a65b667af4d81a93396c4ce238d197626 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 20 Jun 2017 14:18:43 -0700 Subject: [PATCH 044/159] Fix bug #1079, integrality testing seems to have been wrong Signed-off-by: Nikolaj Bjorner --- src/smt/smt_internalizer.cpp | 4 +++- src/smt/theory_arith_aux.h | 7 ++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/smt/smt_internalizer.cpp b/src/smt/smt_internalizer.cpp index f7936eacd..5fbdb2477 100644 --- a/src/smt/smt_internalizer.cpp +++ b/src/smt/smt_internalizer.cpp @@ -1034,8 +1034,10 @@ namespace smt { lbool val = get_assignment(curr); switch(val) { case l_false: + TRACE("simplify_aux_clause_literals", display_literal(tout << get_assign_level(curr) << " " << get_scope_level() << " ", curr); tout << "\n"; ); simp_lits.push_back(~curr); - break; // ignore literal + break; // ignore literal + // fall through case l_undef: if (curr == ~prev) return false; // clause is equivalent to true diff --git a/src/smt/theory_arith_aux.h b/src/smt/theory_arith_aux.h index 54b617152..670121328 100644 --- a/src/smt/theory_arith_aux.h +++ b/src/smt/theory_arith_aux.h @@ -1412,7 +1412,7 @@ namespace smt { << "max gain: " << max_gain << "\n";); - SASSERT(max_gain.is_minus_one() || !max_gain.is_neg()); + SASSERT(max_gain.is_minu SASSERT(min_gain.is_minus_one() || min_gain.is_one()); SASSERT(is_int(x) == min_gain.is_one()); @@ -1458,7 +1458,7 @@ namespace smt { normalize_gain(min_gain.get_rational(), max_gain); } - if (is_int(x_i) && !max_gain.is_rational()) { + if (is_int(x_i) && !max_gain.is_int()) { max_gain = inf_numeral(floor(max_gain)); normalize_gain(min_gain.get_rational(), max_gain); } @@ -1483,7 +1483,7 @@ namespace smt { } } TRACE("opt", - tout << "v" << x_i << " a_ij " << a_ij << " " + tout << "v" << x_i << (is_int(x_i)?" int":" real") << " a_ij " << a_ij << " " << "min gain: " << min_gain << " " << "max gain: " << max_gain << " tighter: " << (is_tighter?"true":"false") << "\n";); @@ -1696,6 +1696,7 @@ namespace smt { if (lower(x_j)) tout << "lower x_j: " << lower_bound(x_j) << " "; tout << "value x_j: " << get_value(x_j) << "\n"; ); + pivot(x_i, x_j, a_ij, false); SASSERT(is_non_base(x_i)); From 0ef14acf2e456475898b79866113d76556693f70 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 20 Jun 2017 14:25:56 -0700 Subject: [PATCH 045/159] fix build break Signed-off-by: Nikolaj Bjorner --- src/smt/theory_arith_aux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smt/theory_arith_aux.h b/src/smt/theory_arith_aux.h index 670121328..679358932 100644 --- a/src/smt/theory_arith_aux.h +++ b/src/smt/theory_arith_aux.h @@ -1412,7 +1412,7 @@ namespace smt { << "max gain: " << max_gain << "\n";); - SASSERT(max_gain.is_minu + SASSERT(max_gain.is_minus_one() || max_gain.is_one()); SASSERT(min_gain.is_minus_one() || min_gain.is_one()); SASSERT(is_int(x) == min_gain.is_one()); From e48e7ef7be6ecf1c9f5b58544f8b3a8e702e910d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 20 Jun 2017 14:37:56 -0700 Subject: [PATCH 046/159] fix assertion, start addressing #1087 by using size_t --- src/smt/theory_arith_aux.h | 2 +- src/smt/theory_str.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/smt/theory_arith_aux.h b/src/smt/theory_arith_aux.h index 679358932..f94de7eba 100644 --- a/src/smt/theory_arith_aux.h +++ b/src/smt/theory_arith_aux.h @@ -1412,7 +1412,7 @@ namespace smt { << "max gain: " << max_gain << "\n";); - SASSERT(max_gain.is_minus_one() || max_gain.is_one()); + SASSERT(max_gain.is_minus_one() || !max_gain.is_neg()); SASSERT(min_gain.is_minus_one() || min_gain.is_one()); SASSERT(is_int(x) == min_gain.is_one()); diff --git a/src/smt/theory_str.cpp b/src/smt/theory_str.cpp index d560a54a1..523e087f2 100644 --- a/src/smt/theory_str.cpp +++ b/src/smt/theory_str.cpp @@ -9194,7 +9194,7 @@ namespace smt { // ---------------------------------------------------------------------------------------- int len = atoi(lenStr.encode().c_str()); bool coverAll = false; - vector options; + vector options; int_vector base; TRACE("str", tout From 69a3e984aa12aaaaa7a1318aad7913dbb035313d Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 20:09:33 -0400 Subject: [PATCH 047/159] add is_hypothesis() method --- src/ast/ast.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ast/ast.h b/src/ast/ast.h index 6bb3b01c9..475e58ac7 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -2082,6 +2082,7 @@ public: bool is_undef_proof(expr const * e) const { return e == m_undef_proof; } bool is_asserted(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_ASSERTED); } + bool is_hypothesis (expr const *e) const {return is_app_of (e, m_basic_family_id, PR_HYPOTHESIS);} bool is_goal(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_GOAL); } bool is_modus_ponens(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_MODUS_PONENS); } bool is_reflexivity(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_REFLEXIVITY); } @@ -2112,6 +2113,7 @@ public: bool is_skolemize(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_SKOLEMIZE); } MATCH_UNARY(is_asserted); + MATCH_UNARY(is_hypothesis); MATCH_UNARY(is_lemma); bool has_fact(proof const * p) const { From e9100854b9c0980b3aad2408e285b572b6448868 Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 20:09:57 -0400 Subject: [PATCH 048/159] ensure that variable names are properly quoted --- src/ast/ast_smt2_pp.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp index 89af8bd3e..d5e46548a 100644 --- a/src/ast/ast_smt2_pp.cpp +++ b/src/ast/ast_smt2_pp.cpp @@ -557,7 +557,14 @@ class smt2_printer { format * f; if (v->get_idx() < m_var_names.size()) { symbol s = m_var_names[m_var_names.size() - v->get_idx() - 1]; - f = mk_string(m(), s.str().c_str()); + std::string vname; + if (is_smt2_quoted_symbol (s)) { + vname = mk_smt2_quoted_symbol (s); + } + else { + vname = s.str(); + } + f = mk_string(m(), vname.c_str ()); } else { // fallback... it is not supposed to happen when the printer is correctly used. @@ -884,7 +891,14 @@ class smt2_printer { symbol * it = m_var_names.end() - num_decls; for (unsigned i = 0; i < num_decls; i++, it++) { format * fs[1] = { m_env.pp_sort(q->get_decl_sort(i)) }; - buf.push_back(mk_seq1(m(), fs, fs+1, f2f(), it->str().c_str())); + std::string var_name; + if (is_smt2_quoted_symbol (*it)) { + var_name = mk_smt2_quoted_symbol (*it); + } + else { + var_name = it->str ();\ + } + buf.push_back(mk_seq1(m(), fs, fs+1, f2f(), var_name.c_str ())); } return mk_seq5(m(), buf.begin(), buf.end(), f2f()); } From 6eced8836d86d39bf1d26dc5137f13f5fa0de19e Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 20:10:22 -0400 Subject: [PATCH 049/159] expose iterators in expr_map --- src/ast/expr_map.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ast/expr_map.h b/src/ast/expr_map.h index ddd94ea13..2b49a4a30 100644 --- a/src/ast/expr_map.h +++ b/src/ast/expr_map.h @@ -35,6 +35,13 @@ class expr_map { obj_map m_expr2expr; obj_map m_expr2pr; public: + typedef obj_map Map; + typedef Map::iterator iterator; + typedef Map::key key; + typedef Map::value value; + typedef Map::data data; + typedef Map::entry entry; + expr_map(ast_manager & m); expr_map(ast_manager & m, bool store_proofs); ~expr_map(); @@ -44,6 +51,8 @@ public: void erase(expr * k); void reset(); void flush(); + iterator begin () const { return m_expr2expr.begin (); } + iterator end () const {return m_expr2expr.end (); } void set_store_proofs(bool f) { if (m_store_proofs != f) flush(); m_store_proofs = f; From f3019a3de964a9e7af6f3bcc9224220647be0d08 Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 20:52:06 -0400 Subject: [PATCH 050/159] api to accumulate stopwatches --- src/util/stopwatch.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/util/stopwatch.h b/src/util/stopwatch.h index b1f6bba03..7a9066030 100644 --- a/src/util/stopwatch.h +++ b/src/util/stopwatch.h @@ -43,6 +43,8 @@ public: } ~stopwatch() {}; + + void add (const stopwatch &s) {/* TODO */} void reset() { m_elapsed.QuadPart = 0; } @@ -90,6 +92,8 @@ public: ~stopwatch() {} + void add (const stopwatch &s) {m_time += s.m_time;} + void reset() { m_time = 0ull; } @@ -141,6 +145,8 @@ public: ~stopwatch() {} + void add (const stopwatch &s) {m_time += s.m_time;} + void reset() { m_time = 0ull; } From 372e8b3c4910954d4df1e466a2000aca7a9b3df0 Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 20:53:04 -0400 Subject: [PATCH 051/159] expose iterator api of obj_hashtable --- src/util/obj_hashtable.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/util/obj_hashtable.h b/src/util/obj_hashtable.h index 383ecaeb3..2720f1b00 100644 --- a/src/util/obj_hashtable.h +++ b/src/util/obj_hashtable.h @@ -70,6 +70,7 @@ public: m_value(v) { } Value const & get_value() const { return m_value; } + Key & get_key () const { return *m_key; } unsigned hash() const { return m_key->hash(); } bool operator==(key_data const & other) const { return m_key == other.m_key; } }; @@ -100,6 +101,8 @@ public: m_table(DEFAULT_HASHTABLE_INITIAL_CAPACITY) {} typedef typename table::iterator iterator; + typedef typename table::data data; + typedef typename table::entry entry; typedef Key key; typedef Value value; From 625874e66fde340fe9ba1399df43b3788026828e Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 20:54:43 -0400 Subject: [PATCH 052/159] remove debug code --- src/tactic/core/blast_term_ite_tactic.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/core/blast_term_ite_tactic.cpp b/src/tactic/core/blast_term_ite_tactic.cpp index ea59641c9..483b59776 100644 --- a/src/tactic/core/blast_term_ite_tactic.cpp +++ b/src/tactic/core/blast_term_ite_tactic.cpp @@ -62,14 +62,14 @@ class blast_term_ite_tactic : public tactic { for (unsigned i = 0; i < num_args; ++i) { expr* c, *t, *e; if (!m.is_bool(args[i]) && m.is_ite(args[i], c, t, e)) { - enable_trace("blast_term_ite"); + // enable_trace("blast_term_ite"); TRACE("blast_term_ite", result = m.mk_app(f, num_args, args); tout << result << "\n";); expr_ref e1(m), e2(m); ptr_vector args1(num_args, args); args1[i] = t; ++m_num_fresh; e1 = m.mk_app(f, num_args, args1.c_ptr()); - if (t == e) { + if (m.are_equal(t,e)) { result = e1; return BR_REWRITE1; } From ac6ca4d334ae957759c911cacb5eeb37b0100309 Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 21:34:49 -0400 Subject: [PATCH 053/159] factored out is_variable_proc to a header file --- src/qe/qe_lite.cpp | 39 +--------------------------- src/qe/qe_vartest.h | 63 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 38 deletions(-) create mode 100644 src/qe/qe_vartest.h diff --git a/src/qe/qe_lite.cpp b/src/qe/qe_lite.cpp index 0e7db9971..62f6c41a6 100644 --- a/src/qe/qe_lite.cpp +++ b/src/qe/qe_lite.cpp @@ -36,44 +36,7 @@ Revision History: #include "cooperate.h" #include "datatype_decl_plugin.h" -class is_variable_proc { -public: - virtual bool operator()(expr* e) const = 0; -}; - -class is_variable_test : public is_variable_proc { - enum is_var_kind { BY_VAR_SET, BY_VAR_SET_COMPLEMENT, BY_NUM_DECLS }; - uint_set m_var_set; - unsigned m_num_decls; - is_var_kind m_var_kind; -public: - is_variable_test(uint_set const& vars, bool index_of_bound) : - m_var_set(vars), - m_num_decls(0), - m_var_kind(index_of_bound?BY_VAR_SET:BY_VAR_SET_COMPLEMENT) {} - - is_variable_test(unsigned num_decls) : - m_num_decls(num_decls), - m_var_kind(BY_NUM_DECLS) {} - - virtual bool operator()(expr* e) const { - if (!is_var(e)) { - return false; - } - unsigned idx = to_var(e)->get_idx(); - switch(m_var_kind) { - case BY_VAR_SET: - return m_var_set.contains(idx); - case BY_VAR_SET_COMPLEMENT: - return !m_var_set.contains(idx); - case BY_NUM_DECLS: - return idx < m_num_decls; - } - UNREACHABLE(); - return false; - } -}; - +#include "qe_vartest.h" namespace eq { class der { diff --git a/src/qe/qe_vartest.h b/src/qe/qe_vartest.h new file mode 100644 index 000000000..b2b4be649 --- /dev/null +++ b/src/qe/qe_vartest.h @@ -0,0 +1,63 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + qe_vartest.h + +Abstract: + + Utilities for quantifiers. + +Author: + + Nikolaj Bjorner (nbjorner) 2013-08-28 + +Revision History: + +--*/ +#ifndef QE_VARTEST_H_ +#define QE_VARTEST_H_ + +#include "ast.h" +#include "uint_set.h" + +class is_variable_proc { +public: + virtual bool operator()(expr* e) const = 0; +}; + +class is_variable_test : public is_variable_proc { + enum is_var_kind { BY_VAR_SET, BY_VAR_SET_COMPLEMENT, BY_NUM_DECLS }; + uint_set m_var_set; + unsigned m_num_decls; + is_var_kind m_var_kind; +public: + is_variable_test(uint_set const& vars, bool index_of_bound) : + m_var_set(vars), + m_num_decls(0), + m_var_kind(index_of_bound?BY_VAR_SET:BY_VAR_SET_COMPLEMENT) {} + + is_variable_test(unsigned num_decls) : + m_num_decls(num_decls), + m_var_kind(BY_NUM_DECLS) {} + + virtual bool operator()(expr* e) const { + if (!is_var(e)) { + return false; + } + unsigned idx = to_var(e)->get_idx(); + switch(m_var_kind) { + case BY_VAR_SET: + return m_var_set.contains(idx); + case BY_VAR_SET_COMPLEMENT: + return !m_var_set.contains(idx); + case BY_NUM_DECLS: + return idx < m_num_decls; + } + UNREACHABLE(); + return false; + } +}; + +#endif From 9f73359a86c634fc31a60db2c0a2c997063df47d Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 21:50:35 -0400 Subject: [PATCH 054/159] improve comments --- src/qe/qe_lite.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/qe/qe_lite.cpp b/src/qe/qe_lite.cpp index 62f6c41a6..e84ab5cb8 100644 --- a/src/qe/qe_lite.cpp +++ b/src/qe/qe_lite.cpp @@ -788,12 +788,13 @@ namespace ar { } /** - Ex A. A[x] = t & Phi where x \not\in A, t. A \not\in t, x + Ex A. A[x] = t & Phi[A] where x \not\in A, t. A \not\in t, x => Ex A. Phi[store(A,x,t)] + (Not implemented) Perhaps also: - Ex A. store(A,y,z)[x] = t & Phi where x \not\in A, t, y, z, A \not\in y z, t + Ex A. store(A,y,z)[x] = t & Phi[A] where x \not\in A, t, y, z, A \not\in y z, t => Ex A, v . (x = y => z = t) & Phi[store(store(A,x,t),y,v)] @@ -822,7 +823,8 @@ namespace ar { expr_safe_replace rep(m); rep.insert(A, B); expr_ref tmp(m); - std::cout << mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n"; + TRACE("qe_lite", + tout << mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n";); for (unsigned j = 0; j < conjs.size(); ++j) { if (i == j) { conjs[j] = m.mk_true(); From ef62621f50eb71a13b9485280a5115e0aa0e3575 Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 21:51:08 -0400 Subject: [PATCH 055/159] make qe_lite prefer simpler definitions --- src/qe/qe_lite.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/qe/qe_lite.cpp b/src/qe/qe_lite.cpp index e84ab5cb8..ce182a97b 100644 --- a/src/qe/qe_lite.cpp +++ b/src/qe/qe_lite.cpp @@ -49,6 +49,7 @@ namespace eq { ptr_vector m_map; int_vector m_pos2var; + int_vector m_var2pos; ptr_vector m_inx2var; unsigned_vector m_order; expr_ref_vector m_subst_map; @@ -541,6 +542,7 @@ namespace eq { largest_vinx = 0; m_map.reset(); m_pos2var.reset(); + m_var2pos.reset(); m_inx2var.reset(); m_pos2var.reserve(num_args, -1); @@ -560,10 +562,48 @@ namespace eq { m_map[idx] = t; m_inx2var[idx] = v; m_pos2var[i] = idx; + m_var2pos.reserve(idx + 1, -1); + m_var2pos[idx] = i; def_count++; largest_vinx = std::max(idx, largest_vinx); m_new_exprs.push_back(t); } + else if (!m.is_value(m_map[idx])) { + // check if the new definition is simpler + expr *old_def = m_map[idx]; + + // -- prefer values + if (m.is_value(t)) { + m_pos2var[m_var2pos[idx]] = -1; + m_pos2var[i] = idx; + m_var2pos[idx] = i; + m_map[idx] = t; + m_new_exprs.push_back(t); + } + // -- prefer ground + else if (is_app(t) && to_app(t)->is_ground() && + (!is_app(old_def) || + !to_app(old_def)->is_ground())) { + m_pos2var[m_var2pos[idx]] = -1; + m_pos2var[i] = idx; + m_var2pos[idx] = i; + m_map[idx] = t; + m_new_exprs.push_back(t); + } + // -- prefer constants + else if (is_uninterp_const(t) + /* && !is_uninterp_const(old_def) */){ + m_pos2var[m_var2pos[idx]] = -1; + m_pos2var[i] = idx; + m_var2pos[idx] = i; + m_map[idx] = t; + m_new_exprs.push_back(t); + } + TRACE ("qe_def", + tout << "Replacing definition of VAR " << idx << " from " + << mk_pp(old_def, m) << " to " << mk_pp(t, m) + << " inferred from: " << mk_pp(args[i], m) << "\n";); + } } } } From 7840f6cead3e305d53293150d8625da47912e45a Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 22:17:35 -0400 Subject: [PATCH 056/159] typo in a comment --- src/muz/transforms/dl_mk_slice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/muz/transforms/dl_mk_slice.cpp b/src/muz/transforms/dl_mk_slice.cpp index 2f7d0d475..aa910002d 100644 --- a/src/muz/transforms/dl_mk_slice.cpp +++ b/src/muz/transforms/dl_mk_slice.cpp @@ -22,7 +22,7 @@ Revision History: input: x, z output: x, y - Let x_i, y_i, z_i be incides into the vectors x, y, z. + Let x_i, y_i, z_i be indices into the vectors x, y, z. Suppose that positions in P and R are annotated with what is slicable. From 50f794c4f59e2717ef35375810a5c84d0527d239 Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 22:08:52 -0400 Subject: [PATCH 057/159] api for accessing dl_rule name --- src/muz/base/dl_rule.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/muz/base/dl_rule.h b/src/muz/base/dl_rule.h index f7dc18b5e..856814531 100644 --- a/src/muz/base/dl_rule.h +++ b/src/muz/base/dl_rule.h @@ -298,7 +298,7 @@ namespace datalog { static unsigned get_obj_size(unsigned n) { return sizeof(rule) + n * sizeof(app *); } - rule() : m_ref_cnt(0) {} + rule() : m_ref_cnt(0), m_name(symbol::null) {} ~rule() {} void deallocate(ast_manager & m); @@ -355,7 +355,12 @@ namespace datalog { void display(context & ctx, std::ostream & out) const; - symbol const& name() const { return m_name; } + /** + \brief Return the name(s) associated with this rule. Plural for preprocessed (e.g. obtained by inlining) rules. + + This possibly returns a ";"-separated list of names. + */ + symbol const& name() const { return m_name; } ; unsigned hash() const; From af280579804c5af624b89b9bbb172f7c3e1a30fe Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 22:04:35 -0400 Subject: [PATCH 058/159] preserve dl rule names during xforms --- src/muz/base/dl_rule.cpp | 3 ++- src/muz/transforms/dl_mk_filter_rules.cpp | 2 +- src/muz/transforms/dl_mk_interp_tail_simplifier.cpp | 4 ++-- src/muz/transforms/dl_mk_magic_sets.cpp | 2 +- src/muz/transforms/dl_mk_quantifier_abstraction.cpp | 2 +- src/muz/transforms/dl_mk_quantifier_instantiation.cpp | 2 +- src/muz/transforms/dl_mk_rule_inliner.cpp | 5 ++++- src/muz/transforms/dl_mk_subsumption_checker.cpp | 2 +- 8 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/muz/base/dl_rule.cpp b/src/muz/base/dl_rule.cpp index ffb964f47..27d62538e 100644 --- a/src/muz/base/dl_rule.cpp +++ b/src/muz/base/dl_rule.cpp @@ -784,7 +784,7 @@ namespace datalog { SASSERT(tail.size()==tail_neg.size()); rule_ref old_r = r; - r = mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr()); + r = mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr(), old_r->name()); r->set_accounting_parent_object(m_ctx, old_r); } @@ -1003,6 +1003,7 @@ namespace datalog { void rule::display(context & ctx, std::ostream & out) const { ast_manager & m = ctx.get_manager(); + out << m_name.str () << ":\n"; //out << mk_pp(m_head, m); output_predicate(ctx, m_head, out); if (m_tail_size == 0) { diff --git a/src/muz/transforms/dl_mk_filter_rules.cpp b/src/muz/transforms/dl_mk_filter_rules.cpp index b112f4c99..0d118a589 100644 --- a/src/muz/transforms/dl_mk_filter_rules.cpp +++ b/src/muz/transforms/dl_mk_filter_rules.cpp @@ -140,7 +140,7 @@ namespace datalog { if (rule_modified) { remove_duplicate_tails(new_tail, new_is_negated); SASSERT(new_tail.size() == new_is_negated.size()); - rule * new_rule = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), new_is_negated.c_ptr()); + rule * new_rule = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), new_is_negated.c_ptr(), r->name()); new_rule->set_accounting_parent_object(m_context, m_current); m_result->add_rule(new_rule); m_context.get_rule_manager().mk_rule_rewrite_proof(*r, *new_rule); diff --git a/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp b/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp index 455b06d3d..3c1d1b924 100644 --- a/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp +++ b/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp @@ -84,7 +84,7 @@ namespace datalog { mk_rule_inliner::remove_duplicate_tails(m_tail, m_neg); SASSERT(m_tail.size() == m_neg.size()); - res = m_context.get_rule_manager().mk(m_head, m_tail.size(), m_tail.c_ptr(), m_neg.c_ptr()); + res = m_context.get_rule_manager().mk(m_head, m_tail.size(), m_tail.c_ptr(), m_neg.c_ptr(),m_rule->name()); res->set_accounting_parent_object(m_context, m_rule); res->norm_vars(res.get_manager()); } @@ -557,7 +557,7 @@ namespace datalog { } SASSERT(m_tail.size() == m_tail_neg.size()); - res = m_context.get_rule_manager().mk(head, m_tail.size(), m_tail.c_ptr(), m_tail_neg.c_ptr()); + res = m_context.get_rule_manager().mk(head, m_tail.size(), m_tail.c_ptr(), m_tail_neg.c_ptr(), r->name()); res->set_accounting_parent_object(m_context, r); } else { diff --git a/src/muz/transforms/dl_mk_magic_sets.cpp b/src/muz/transforms/dl_mk_magic_sets.cpp index 048decaf9..19dccf417 100644 --- a/src/muz/transforms/dl_mk_magic_sets.cpp +++ b/src/muz/transforms/dl_mk_magic_sets.cpp @@ -280,7 +280,7 @@ namespace datalog { new_tail.push_back(create_magic_literal(new_head)); negations.push_back(false); - rule * nr = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), negations.c_ptr()); + rule * nr = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), negations.c_ptr(), r->name()); result.add_rule(nr); nr->set_accounting_parent_object(m_context, r); } diff --git a/src/muz/transforms/dl_mk_quantifier_abstraction.cpp b/src/muz/transforms/dl_mk_quantifier_abstraction.cpp index caff79d2e..5c0d442df 100644 --- a/src/muz/transforms/dl_mk_quantifier_abstraction.cpp +++ b/src/muz/transforms/dl_mk_quantifier_abstraction.cpp @@ -341,7 +341,7 @@ namespace datalog { head = mk_head(source, *result, r.get_head(), cnt); fml = m.mk_implies(m.mk_and(tail.size(), tail.c_ptr()), head); proof_ref pr(m); - rm.mk_rule(fml, pr, *result); + rm.mk_rule(fml, pr, *result, r.name()); TRACE("dl", result->last()->display(m_ctx, tout);); } diff --git a/src/muz/transforms/dl_mk_quantifier_instantiation.cpp b/src/muz/transforms/dl_mk_quantifier_instantiation.cpp index 5d36d26cc..586c52cd6 100644 --- a/src/muz/transforms/dl_mk_quantifier_instantiation.cpp +++ b/src/muz/transforms/dl_mk_quantifier_instantiation.cpp @@ -232,7 +232,7 @@ namespace datalog { rule_set added_rules(m_ctx); proof_ref pr(m); - rm.mk_rule(fml, pr, added_rules); + rm.mk_rule(fml, pr, added_rules, r.name()); if (r.get_proof()) { // use def-axiom to encode that new rule is a weakening of the original. proof* p1 = r.get_proof(); diff --git a/src/muz/transforms/dl_mk_rule_inliner.cpp b/src/muz/transforms/dl_mk_rule_inliner.cpp index 7dabece2f..c6b3e8be7 100644 --- a/src/muz/transforms/dl_mk_rule_inliner.cpp +++ b/src/muz/transforms/dl_mk_rule_inliner.cpp @@ -114,7 +114,10 @@ namespace datalog { apply(src, false, UINT_MAX, tail, tail_neg); mk_rule_inliner::remove_duplicate_tails(tail, tail_neg); SASSERT(tail.size()==tail_neg.size()); - res = m_rm.mk(new_head, tail.size(), tail.c_ptr(), tail_neg.c_ptr(), tgt.name(), m_normalize); + std::ostringstream comb_name; + comb_name << tgt.name().str() << ";" << src.name().str(); + symbol combined_rule_name = symbol(comb_name.str().c_str()); + res = m_rm.mk(new_head, tail.size(), tail.c_ptr(), tail_neg.c_ptr(), combined_rule_name, m_normalize); res->set_accounting_parent_object(m_context, const_cast(&tgt)); TRACE("dl", tgt.display(m_context, tout << "tgt (" << tail_index << "): \n"); diff --git a/src/muz/transforms/dl_mk_subsumption_checker.cpp b/src/muz/transforms/dl_mk_subsumption_checker.cpp index 1967fdc93..8fae4ee35 100644 --- a/src/muz/transforms/dl_mk_subsumption_checker.cpp +++ b/src/muz/transforms/dl_mk_subsumption_checker.cpp @@ -159,7 +159,7 @@ namespace datalog { } SASSERT(tail.size()==tail_neg.size()); - res = m_context.get_rule_manager().mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr()); + res = m_context.get_rule_manager().mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr(), r->name()); res->set_accounting_parent_object(m_context, r); m_context.get_rule_manager().fix_unbound_vars(res, true); m_context.get_rule_manager().mk_rule_rewrite_proof(*r, *res.get()); From a3ee7859234779181facbb2b35dbaa2f5da785e5 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 21 Jun 2017 07:29:21 -0700 Subject: [PATCH 059/159] disable dt2bv for quantified variables as enum2bv does not handle them. #1092 Signed-off-by: Nikolaj Bjorner --- src/tactic/bv/dt2bv_tactic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/bv/dt2bv_tactic.cpp b/src/tactic/bv/dt2bv_tactic.cpp index 2b9cfb7f3..cac6f1f5d 100644 --- a/src/tactic/bv/dt2bv_tactic.cpp +++ b/src/tactic/bv/dt2bv_tactic.cpp @@ -82,7 +82,7 @@ class dt2bv_tactic : public tactic { void operator()(var * v) { if (m_t.is_fd(v)) { - m_t.m_fd_sorts.insert(get_sort(v)); + m_t.m_non_fd_sorts.insert(get_sort(v)); } } From b516f2254990cd0d56ae81652c260cfdc3e164b6 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 21 Jun 2017 08:01:03 -0700 Subject: [PATCH 060/159] refine test for non-fd to be more inclusive while addressing #1092 Signed-off-by: Nikolaj Bjorner --- src/ast/ast.h | 2 ++ src/tactic/bv/dt2bv_tactic.cpp | 31 +++++++++++++++++-------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/ast/ast.h b/src/ast/ast.h index 475e58ac7..f71d5135c 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -667,6 +667,8 @@ public: expr * get_arg(unsigned idx) const { SASSERT(idx < m_num_args); return m_args[idx]; } expr * const * get_args() const { return m_args; } unsigned get_size() const { return get_obj_size(get_num_args()); } + expr * const * begin() const { return m_args; } + expr * const * end() const { return m_args + m_num_args; } unsigned get_depth() const { return flags()->m_depth; } bool is_ground() const { return flags()->m_ground; } diff --git a/src/tactic/bv/dt2bv_tactic.cpp b/src/tactic/bv/dt2bv_tactic.cpp index cac6f1f5d..3ae72215f 100644 --- a/src/tactic/bv/dt2bv_tactic.cpp +++ b/src/tactic/bv/dt2bv_tactic.cpp @@ -30,6 +30,7 @@ Revision History: #include "var_subst.h" #include "ast_util.h" #include "enum2bv_rewriter.h" +#include "ast_pp.h" class dt2bv_tactic : public tactic { @@ -53,36 +54,38 @@ class dt2bv_tactic : public tactic { void operator()(app* a) { if (m.is_eq(a)) { - return; + // no-op } - if (m.is_distinct(a)) { - return; + else if (m.is_distinct(a)) { + // no-op } - if (m_t.m_dt.is_recognizer(a->get_decl()) && + else if (m_t.m_dt.is_recognizer(a->get_decl()) && m_t.is_fd(a->get_arg(0))) { m_t.m_fd_sorts.insert(get_sort(a->get_arg(0))); - return; } - - if (m_t.is_fd(a) && a->get_num_args() > 0) { + else if (m_t.is_fd(a) && a->get_num_args() > 0) { m_t.m_non_fd_sorts.insert(get_sort(a)); + args_cannot_be_fd(a); } else if (m_t.is_fd(a)) { m_t.m_fd_sorts.insert(get_sort(a)); } else { - unsigned sz = a->get_num_args(); - for (unsigned i = 0; i < sz; ++i) { - if (m_t.is_fd(a->get_arg(i))) { - m_t.m_non_fd_sorts.insert(get_sort(a->get_arg(i))); - } - } + args_cannot_be_fd(a); + } + } + + void args_cannot_be_fd(app* a) { + for (expr* arg : *a) { + if (m_t.is_fd(arg)) { + m_t.m_non_fd_sorts.insert(get_sort(arg)); + } } } void operator()(var * v) { if (m_t.is_fd(v)) { - m_t.m_non_fd_sorts.insert(get_sort(v)); + m_t.m_fd_sorts.insert(get_sort(v)); } } From 229fd3dc3e6123ef207146161686dd22f9ea76e9 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Wed, 21 Jun 2017 18:36:20 +0100 Subject: [PATCH 061/159] [CMake] Fix dependencies for generating `install_tactic.cpp`. Previously CMake was not aware of which headers files the generation of `install_tactic.cpp` depended on. Consequently this could result in broken incremental builds if * Existing headers that declared tactics/probes changed. * New tactics/probes were added to new header files. Now the `z3_add_component()` CMake function has been modifed to take an optional `TACTIC_HEADERS` argument which allows the headers that declare tactics/probes to be explicitly listed. The necessary component declarations have been modified to declare their tactic/probe header files. With this information CMake will now regenerate `install_tactic.cpp` correctly. This required the `mk_install_tactic_cpp_internal()` function to be changed to take a list of header files rather than a list of component source directories. The two consumers (CMake and Python/Makefile build systems) of this function have been modified to work with this change. This partially fixes #1030. --- cmake/z3_add_component.cmake | 41 ++++++++++++++++++++---- scripts/mk_genfile_common.py | 16 ++++----- scripts/mk_install_tactic_cpp.py | 23 ++++++------- scripts/mk_util.py | 12 ++++++- src/ackermannization/CMakeLists.txt | 3 ++ src/math/subpaving/tactic/CMakeLists.txt | 2 ++ src/muz/fp/CMakeLists.txt | 2 ++ src/nlsat/tactic/CMakeLists.txt | 3 ++ src/qe/CMakeLists.txt | 11 +++++-- src/sat/tactic/CMakeLists.txt | 2 ++ src/smt/tactic/CMakeLists.txt | 4 +++ src/tactic/CMakeLists.txt | 4 +++ src/tactic/aig/CMakeLists.txt | 2 ++ src/tactic/arith/CMakeLists.txt | 19 +++++++++++ src/tactic/bv/CMakeLists.txt | 10 ++++++ src/tactic/core/CMakeLists.txt | 21 +++++++++++- src/tactic/fpa/CMakeLists.txt | 3 ++ src/tactic/nlsat_smt/CMakeLists.txt | 2 ++ src/tactic/portfolio/CMakeLists.txt | 2 ++ src/tactic/sls/CMakeLists.txt | 2 ++ src/tactic/smtlogics/CMakeLists.txt | 14 ++++++++ src/tactic/ufbv/CMakeLists.txt | 5 +++ 22 files changed, 171 insertions(+), 32 deletions(-) diff --git a/cmake/z3_add_component.cmake b/cmake/z3_add_component.cmake index b90aa2fe7..43a634ae1 100644 --- a/cmake/z3_add_component.cmake +++ b/cmake/z3_add_component.cmake @@ -55,6 +55,7 @@ endfunction() # SOURCES source1 [source2...] # [COMPONENT_DEPENDENCIES component1 [component2...]] # [PYG_FILES pygfile1 [pygfile2...]] +# [TACTIC_HEADERS header_file1 [header_file2...]] # ) # # Declares a Z3 component (as a CMake "object library") with target name @@ -81,8 +82,11 @@ endfunction() # more ``.pyg`` files that should used to be generate # ``_params.hpp`` header files used by the ``component_name``. # +# The optional ``TACTIC_HEADERS`` keyword should be followed by a list of one or +# more header files that declare a tactic and/or a probe that is part of this +# component (see ``ADD_TACTIC()`` and ``ADD_PROBE()``). macro(z3_add_component component_name) - CMAKE_PARSE_ARGUMENTS("Z3_MOD" "NOT_LIBZ3_COMPONENT" "" "SOURCES;COMPONENT_DEPENDENCIES;PYG_FILES" ${ARGN}) + CMAKE_PARSE_ARGUMENTS("Z3_MOD" "NOT_LIBZ3_COMPONENT" "" "SOURCES;COMPONENT_DEPENDENCIES;PYG_FILES;TACTIC_HEADERS" ${ARGN}) message(STATUS "Adding component ${component_name}") # Note: We don't check the sources exist here because # they might be generated files that don't exist yet. @@ -117,6 +121,21 @@ macro(z3_add_component component_name) unset(_full_output_file_path) unset(_output_file) + # Add tactic/probe headers to global property + set_property(GLOBAL PROPERTY Z3_${component_name}_TACTIC_HEADERS "") + foreach (tactic_header ${Z3_MOD_TACTIC_HEADERS}) + set(_full_tactic_header_file_path "${CMAKE_CURRENT_SOURCE_DIR}/${tactic_header}") + if (NOT (EXISTS "${_full_tactic_header_file_path}")) + message(FATAL_ERROR "\"${_full_tactic_header_file_path}\" does not exist") + endif() + set_property(GLOBAL + APPEND + PROPERTY Z3_${component_name}_TACTIC_HEADERS + "${_full_tactic_header_file_path}" + ) + endforeach() + unset(_full_tactic_header_file_path) + # Using "object" libraries here means we have a convenient # name to refer to a component in CMake but we don't actually # create a static/library from them. This allows us to easily @@ -191,25 +210,33 @@ macro(z3_add_install_tactic_rule) ) endif() z3_expand_dependencies(_expanded_components ${ARGN}) - # Get paths to search - set(_search_paths "") + + # Get header files that declare tactics/probes + set(_tactic_header_files "") foreach (dependency ${_expanded_components}) - get_property(_dep_include_dirs GLOBAL PROPERTY Z3_${dependency}_INCLUDES) - list(APPEND _search_paths ${_dep_include_dirs}) + get_property(_component_tactic_header_files + GLOBAL + PROPERTY Z3_${dependency}_TACTIC_HEADERS + ) + list(APPEND _tactic_header_files ${_component_tactic_header_files}) endforeach() + unset(_component_tactic_header_files) + list(APPEND _search_paths "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") add_custom_command(OUTPUT "install_tactic.cpp" COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/mk_install_tactic_cpp.py" "${CMAKE_CURRENT_BINARY_DIR}" - ${_search_paths} + ${_tactic_header_files} DEPENDS "${CMAKE_SOURCE_DIR}/scripts/mk_install_tactic_cpp.py" ${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES} - ${_expanded_components} + ${_tactic_header_files} COMMENT "Generating \"${CMAKE_CURRENT_BINARY_DIR}/install_tactic.cpp\"" ${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG} VERBATIM ) + unset(_expanded_components) + unset(_tactic_header_files) endmacro() macro(z3_add_memory_initializer_rule) diff --git a/scripts/mk_genfile_common.py b/scripts/mk_genfile_common.py index 98346f99f..1a2a2dad7 100644 --- a/scripts/mk_genfile_common.py +++ b/scripts/mk_genfile_common.py @@ -651,7 +651,7 @@ def mk_gparams_register_modules_internal(component_src_dirs, path): # Functions/data structures for generating ``install_tactics.cpp`` ############################################################################### -def mk_install_tactic_cpp_internal(component_src_dirs, path): +def mk_install_tactic_cpp_internal(h_files_full_path, path): """ Generate a ``install_tactics.cpp`` file in the directory ``path``. Returns the path the generated file. @@ -662,9 +662,10 @@ def mk_install_tactic_cpp_internal(component_src_dirs, path): void install_tactics(tactic_manager & ctx) ``` - It installs all tactics found in the given component directories - ``component_src_dirs`` The procedure looks for ``ADD_TACTIC`` commands - in the ``.h`` and ``.hpp`` files of these components. + It installs all tactics declared in the given header files + ``h_files_full_path`` The procedure looks for ``ADD_TACTIC`` and + ``ADD_PROBE``commands in the ``.h`` and ``.hpp`` files of these + components. """ ADD_TACTIC_DATA = [] ADD_PROBE_DATA = [] @@ -679,7 +680,7 @@ def mk_install_tactic_cpp_internal(component_src_dirs, path): 'ADD_PROBE': ADD_PROBE, } - assert isinstance(component_src_dirs, list) + assert isinstance(h_files_full_path, list) assert check_dir_exists(path) fullname = os.path.join(path, 'install_tactic.cpp') fout = open(fullname, 'w') @@ -689,11 +690,6 @@ def mk_install_tactic_cpp_internal(component_src_dirs, path): fout.write('#include"cmd_context.h"\n') tactic_pat = re.compile('[ \t]*ADD_TACTIC\(.*\)') probe_pat = re.compile('[ \t]*ADD_PROBE\(.*\)') - h_files_full_path = [] - for component_src_dir in sorted(component_src_dirs): - h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(component_src_dir)) - h_files = list(map(lambda p: os.path.join(component_src_dir, p), h_files)) - h_files_full_path.extend(h_files) for h_file in sorted_headers_by_component(h_files_full_path): added_include = False with open(h_file, 'r') as fin: diff --git a/scripts/mk_install_tactic_cpp.py b/scripts/mk_install_tactic_cpp.py index 21e66b3ab..a152eff14 100755 --- a/scripts/mk_install_tactic_cpp.py +++ b/scripts/mk_install_tactic_cpp.py @@ -1,10 +1,8 @@ #!/usr/bin/env python """ -Determines the available tactics -in header files in the list of source directions -and generates a ``install_tactic.cpp`` file in -the destination directory that defines a function -``void install_tactics(tactic_manager& ctx)``. +Determines the available tactics from a list of header files and generates a +``install_tactic.cpp`` file in the destination directory that defines a +function ``void install_tactics(tactic_manager& ctx)``. """ import mk_genfile_common import argparse @@ -16,19 +14,22 @@ def main(args): logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("destination_dir", help="destination directory") - parser.add_argument("source_dirs", nargs="+", - help="One or more source directories to search") + parser.add_argument("header_files", nargs="+", + help="One or more header files to parse") pargs = parser.parse_args(args) if not mk_genfile_common.check_dir_exists(pargs.destination_dir): return 1 - for source_dir in pargs.source_dirs: - if not mk_genfile_common.check_dir_exists(source_dir): - return 1 + if not mk_genfile_common.check_files_exist(pargs.header_files): + return 1 + + h_files_full_path = [] + for header_file in pargs.header_files: + h_files_full_path.append(os.path.abspath(header_file)) output = mk_genfile_common.mk_install_tactic_cpp_internal( - pargs.source_dirs, + h_files_full_path, pargs.destination_dir ) logging.info('Generated "{}"'.format(output)) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index e7e35817f..b5924d0d1 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2712,12 +2712,22 @@ def mk_all_assembly_infos(major, minor, build, revision): else: raise MKException("Failed to find assembly template info file '%s'" % assembly_info_template) +def get_header_files_for_components(component_src_dirs): + assert isinstance(component_src_dirs, list) + h_files_full_path = [] + for component_src_dir in sorted(component_src_dirs): + h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(component_src_dir)) + h_files = list(map(lambda p: os.path.join(component_src_dir, p), h_files)) + h_files_full_path.extend(h_files) + return h_files_full_path + def mk_install_tactic_cpp(cnames, path): component_src_dirs = [] for cname in cnames: c = get_component(cname) component_src_dirs.append(c.src_dir) - generated_file = mk_genfile_common.mk_install_tactic_cpp_internal(component_src_dirs, path) + h_files_full_path = get_header_files_for_components(component_src_dirs) + generated_file = mk_genfile_common.mk_install_tactic_cpp_internal(h_files_full_path, path) if VERBOSE: print("Generated '{}'".format(generated_file)) diff --git a/src/ackermannization/CMakeLists.txt b/src/ackermannization/CMakeLists.txt index 93529ae12..3ce7f97cc 100644 --- a/src/ackermannization/CMakeLists.txt +++ b/src/ackermannization/CMakeLists.txt @@ -17,4 +17,7 @@ z3_add_component(ackermannization PYG_FILES ackermannization_params.pyg ackermannize_bv_tactic_params.pyg + TACTIC_HEADERS + ackermannize_bv_tactic.h + ackr_bound_probe.h ) diff --git a/src/math/subpaving/tactic/CMakeLists.txt b/src/math/subpaving/tactic/CMakeLists.txt index eedb0ed4d..8873a1021 100644 --- a/src/math/subpaving/tactic/CMakeLists.txt +++ b/src/math/subpaving/tactic/CMakeLists.txt @@ -5,4 +5,6 @@ z3_add_component(subpaving_tactic COMPONENT_DEPENDENCIES core_tactics subpaving + TACTIC_HEADERS + subpaving_tactic.h ) diff --git a/src/muz/fp/CMakeLists.txt b/src/muz/fp/CMakeLists.txt index 239c4df12..4a7c4d018 100644 --- a/src/muz/fp/CMakeLists.txt +++ b/src/muz/fp/CMakeLists.txt @@ -13,4 +13,6 @@ z3_add_component(fp pdr rel tab + TACTIC_HEADERS + horn_tactic.h ) diff --git a/src/nlsat/tactic/CMakeLists.txt b/src/nlsat/tactic/CMakeLists.txt index 9ea26a0c5..3be3bcfb7 100644 --- a/src/nlsat/tactic/CMakeLists.txt +++ b/src/nlsat/tactic/CMakeLists.txt @@ -7,4 +7,7 @@ z3_add_component(nlsat_tactic arith_tactics nlsat sat_tactic + TACTIC_HEADERS + nlsat_tactic.h + qfnra_nlsat_tactic.h ) diff --git a/src/qe/CMakeLists.txt b/src/qe/CMakeLists.txt index 6e82e2c96..2d2cf9579 100644 --- a/src/qe/CMakeLists.txt +++ b/src/qe/CMakeLists.txt @@ -23,6 +23,13 @@ z3_add_component(qe nlsat_tactic nlsat sat - smt - tactic + smt + tactic + TACTIC_HEADERS + nlqsat.h + qe_lite.h + qe_sat_tactic.h + qe_tactic.h + qsat.h + vsubst_tactic.h ) diff --git a/src/sat/tactic/CMakeLists.txt b/src/sat/tactic/CMakeLists.txt index 74aeba8b9..fed6a89c8 100644 --- a/src/sat/tactic/CMakeLists.txt +++ b/src/sat/tactic/CMakeLists.txt @@ -6,4 +6,6 @@ z3_add_component(sat_tactic COMPONENT_DEPENDENCIES sat tactic + TACTIC_HEADERS + sat_tactic.h ) diff --git a/src/smt/tactic/CMakeLists.txt b/src/smt/tactic/CMakeLists.txt index b7525bda8..6187f9c18 100644 --- a/src/smt/tactic/CMakeLists.txt +++ b/src/smt/tactic/CMakeLists.txt @@ -5,4 +5,8 @@ z3_add_component(smt_tactic unit_subsumption_tactic.cpp COMPONENT_DEPENDENCIES smt + TACTIC_HEADERS + ctx_solver_simplify_tactic.h + smt_tactic.h + unit_subsumption_tactic.h ) diff --git a/src/tactic/CMakeLists.txt b/src/tactic/CMakeLists.txt index 324d8089b..e7cfdb644 100644 --- a/src/tactic/CMakeLists.txt +++ b/src/tactic/CMakeLists.txt @@ -18,4 +18,8 @@ z3_add_component(tactic COMPONENT_DEPENDENCIES ast model + TACTIC_HEADERS + probe.h + sine_filter.h + tactic.h ) diff --git a/src/tactic/aig/CMakeLists.txt b/src/tactic/aig/CMakeLists.txt index 1e1a0d266..51ea9b6d3 100644 --- a/src/tactic/aig/CMakeLists.txt +++ b/src/tactic/aig/CMakeLists.txt @@ -4,4 +4,6 @@ z3_add_component(aig_tactic aig_tactic.cpp COMPONENT_DEPENDENCIES tactic + TACTIC_HEADERS + aig_tactic.h ) diff --git a/src/tactic/arith/CMakeLists.txt b/src/tactic/arith/CMakeLists.txt index cdc42367a..335020838 100644 --- a/src/tactic/arith/CMakeLists.txt +++ b/src/tactic/arith/CMakeLists.txt @@ -28,4 +28,23 @@ z3_add_component(arith_tactics COMPONENT_DEPENDENCIES core_tactics sat + TACTIC_HEADERS + add_bounds_tactic.h + card2bv_tactic.h + degree_shift_tactic.h + diff_neq_tactic.h + elim01_tactic.h + eq2bv_tactic.h + factor_tactic.h + fix_dl_var_tactic.h + fm_tactic.h + lia2pb_tactic.h + lia2card_tactic.h + nla2bv_tactic.h + normalize_bounds_tactic.h + pb2bv_tactic.h + probe_arith.h + propagate_ineqs_tactic.h + purify_arith_tactic.h + recover_01_tactic.h ) diff --git a/src/tactic/bv/CMakeLists.txt b/src/tactic/bv/CMakeLists.txt index 90ed65e3f..e9f0927d5 100644 --- a/src/tactic/bv/CMakeLists.txt +++ b/src/tactic/bv/CMakeLists.txt @@ -15,4 +15,14 @@ z3_add_component(bv_tactics bit_blaster core_tactics tactic + TACTIC_HEADERS + bit_blaster_tactic.h + bv1_blaster_tactic.h + bv_bound_chk_tactic.h + bv_bounds_tactic.h + bv_size_reduction_tactic.h + bvarray2uf_tactic.h + dt2bv_tactic.h + elim_small_bv_tactic.h + max_bv_sharing_tactic.h ) diff --git a/src/tactic/core/CMakeLists.txt b/src/tactic/core/CMakeLists.txt index fcd26bd84..1f766bd47 100644 --- a/src/tactic/core/CMakeLists.txt +++ b/src/tactic/core/CMakeLists.txt @@ -3,7 +3,7 @@ z3_add_component(core_tactics blast_term_ite_tactic.cpp cofactor_elim_term_ite.cpp cofactor_term_ite_tactic.cpp - collect_statistics_tactic.cpp + collect_statistics_tactic.cpp ctx_simplify_tactic.cpp der_tactic.cpp distribute_forall_tactic.cpp @@ -23,5 +23,24 @@ z3_add_component(core_tactics COMPONENT_DEPENDENCIES normal_forms tactic + TACTIC_HEADERS + blast_term_ite_tactic.h + cofactor_term_ite_tactic.h + collect_statistics_tactic.h + ctx_simplify_tactic.h + der_tactic.h + distribute_forall_tactic.h + elim_term_ite_tactic.h + elim_uncnstr_tactic.h + nnf_tactic.h + occf_tactic.h + pb_preprocess_tactic.h + propagate_values_tactic.h + reduce_args_tactic.h + simplify_tactic.h + solve_eqs_tactic.h + split_clause_tactic.h + symmetry_reduce_tactic.h + tseitin_cnf_tactic.h ) diff --git a/src/tactic/fpa/CMakeLists.txt b/src/tactic/fpa/CMakeLists.txt index d93cd5b82..a54212235 100644 --- a/src/tactic/fpa/CMakeLists.txt +++ b/src/tactic/fpa/CMakeLists.txt @@ -11,4 +11,7 @@ z3_add_component(fpa_tactics sat_tactic smtlogic_tactics smt_tactic + TACTIC_HEADERS + fpa2bv_tactic.h + qffp_tactic.h ) diff --git a/src/tactic/nlsat_smt/CMakeLists.txt b/src/tactic/nlsat_smt/CMakeLists.txt index e28b11966..ccfc0e3ef 100644 --- a/src/tactic/nlsat_smt/CMakeLists.txt +++ b/src/tactic/nlsat_smt/CMakeLists.txt @@ -4,4 +4,6 @@ z3_add_component(nlsat_smt_tactic COMPONENT_DEPENDENCIES nlsat_tactic smt_tactic + TACTIC_HEADERS + nl_purify_tactic.h ) diff --git a/src/tactic/portfolio/CMakeLists.txt b/src/tactic/portfolio/CMakeLists.txt index c6f621f25..a8a9b2bba 100644 --- a/src/tactic/portfolio/CMakeLists.txt +++ b/src/tactic/portfolio/CMakeLists.txt @@ -16,4 +16,6 @@ z3_add_component(portfolio smtlogic_tactics subpaving_tactic ufbv_tactic + TACTIC_HEADERS + default_tactic.h ) diff --git a/src/tactic/sls/CMakeLists.txt b/src/tactic/sls/CMakeLists.txt index 8b720b333..436b1742f 100644 --- a/src/tactic/sls/CMakeLists.txt +++ b/src/tactic/sls/CMakeLists.txt @@ -10,4 +10,6 @@ z3_add_component(sls_tactic tactic PYG_FILES sls_params.pyg + TACTIC_HEADERS + sls_tactic.h ) diff --git a/src/tactic/smtlogics/CMakeLists.txt b/src/tactic/smtlogics/CMakeLists.txt index 840dd008a..c90fd7468 100644 --- a/src/tactic/smtlogics/CMakeLists.txt +++ b/src/tactic/smtlogics/CMakeLists.txt @@ -28,4 +28,18 @@ z3_add_component(smtlogic_tactics smt_tactic PYG_FILES qfufbv_tactic_params.pyg + TACTIC_HEADERS + nra_tactic.h + qfaufbv_tactic.h + qfauflia_tactic.h + qfbv_tactic.h + qfidl_tactic.h + qflia_tactic.h + qflra_tactic.h + qfnia_tactic.h + qfnra_tactic.h + qfuf_tactic.h + qfufbv_tactic.h + qfufnra_tactic.h + quant_tactics.h ) diff --git a/src/tactic/ufbv/CMakeLists.txt b/src/tactic/ufbv/CMakeLists.txt index c1d6daaaa..511dc2b2d 100644 --- a/src/tactic/ufbv/CMakeLists.txt +++ b/src/tactic/ufbv/CMakeLists.txt @@ -11,4 +11,9 @@ z3_add_component(ufbv_tactic normal_forms rewriter smt_tactic + TACTIC_HEADERS + macro_finder_tactic.h + quasi_macros_tactic.h + ufbv_rewriter_tactic.h + ufbv_tactic.h ) From 6f48a145aaafe3bc28f1239f3f13325a7d4eeaef Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Wed, 21 Jun 2017 22:56:31 +0100 Subject: [PATCH 062/159] [CMake] Fix dependencies for generating `gparams_register_modules.cpp`. Previously CMake was not aware of which headers files the generation of `gparams_register_modules.cpp` depended on. Consequently this could result in broken incremental builds if * Existing headers that declared module description/parameters change. * New headers are added that declare module description/parameters. * `.pyg` files that generate header files that declare module description/parameters change Now the `z3_add_component()` CMake function has been modifed so that * All header files that are generated from `.pyg` files are added as dependencies and are scanned from module description/parameter declarations. This implicit dependency of `gparams_register_modules.cpp` depending on other generated header files seems unnecessary complex. We should revisit this design decision once the Python/Makefile build system is deprecated. * The function now takes an optional `EXTRA_REGISTER_MODULE_HEADERS` argument which allows the headers that declare module description/paramters to be explicitly listed. With this information CMake will now regenerate `gparams_register_modules.cpp` correctly. This required the `mk_gparams_register_modules_internal()` function to be changed to take a list of header files rather than a list of component source directories. The two consumers (CMake and Python/Makefile build systems) of this function have been modified to work with this change. This partially fixes #1030. --- cmake/z3_add_component.cmake | 60 +++++++++++++++++++--- scripts/mk_genfile_common.py | 9 +--- scripts/mk_gparams_register_modules_cpp.py | 23 +++++---- scripts/mk_util.py | 3 +- src/ast/normal_forms/CMakeLists.txt | 2 + src/cmd_context/CMakeLists.txt | 2 + src/math/polynomial/CMakeLists.txt | 2 + src/util/CMakeLists.txt | 2 + 8 files changed, 76 insertions(+), 27 deletions(-) diff --git a/cmake/z3_add_component.cmake b/cmake/z3_add_component.cmake index 43a634ae1..489dc3ee2 100644 --- a/cmake/z3_add_component.cmake +++ b/cmake/z3_add_component.cmake @@ -56,6 +56,7 @@ endfunction() # [COMPONENT_DEPENDENCIES component1 [component2...]] # [PYG_FILES pygfile1 [pygfile2...]] # [TACTIC_HEADERS header_file1 [header_file2...]] +# [EXTRA_REGISTER_MODULE_HEADERS header_file1 [header_file2...]] # ) # # Declares a Z3 component (as a CMake "object library") with target name @@ -81,17 +82,28 @@ endfunction() # The optional ``PYG_FILES`` keyword should be followed by a list of one or # more ``.pyg`` files that should used to be generate # ``_params.hpp`` header files used by the ``component_name``. +# This generated file will automatically be scanned for the register module +# declarations (i.e. ``REG_PARAMS()``, ``REG_MODULE_PARAMS()``, and +# ``REG_MODULE_DESCRIPTION()``). # # The optional ``TACTIC_HEADERS`` keyword should be followed by a list of one or # more header files that declare a tactic and/or a probe that is part of this # component (see ``ADD_TACTIC()`` and ``ADD_PROBE()``). +# +# The optional ``EXTRA_REGISTER_MODULE_HEADERS`` keyword should be followed by a list +# of one or more header files that contain module registration declarations. +# NOTE: The header files generated from ``.pyg`` files don't need to be included. macro(z3_add_component component_name) - CMAKE_PARSE_ARGUMENTS("Z3_MOD" "NOT_LIBZ3_COMPONENT" "" "SOURCES;COMPONENT_DEPENDENCIES;PYG_FILES;TACTIC_HEADERS" ${ARGN}) + CMAKE_PARSE_ARGUMENTS("Z3_MOD" + "NOT_LIBZ3_COMPONENT" + "" + "SOURCES;COMPONENT_DEPENDENCIES;PYG_FILES;TACTIC_HEADERS;EXTRA_REGISTER_MODULE_HEADERS" ${ARGN}) message(STATUS "Adding component ${component_name}") # Note: We don't check the sources exist here because # they might be generated files that don't exist yet. set(_list_generated_headers "") + set_property(GLOBAL PROPERTY Z3_${component_name}_REGISTER_MODULE_HEADERS "") foreach (pyg_file ${Z3_MOD_PYG_FILES}) set(_full_pyg_file_path "${CMAKE_CURRENT_SOURCE_DIR}/${pyg_file}") if (NOT (EXISTS "${_full_pyg_file_path}")) @@ -116,6 +128,18 @@ macro(z3_add_component component_name) VERBATIM ) list(APPEND _list_generated_headers "${_full_output_file_path}") + + # FIXME: This implicit dependency of a generated file depending on + # generated files was inherited from the old build system. + + # Typically generated headers contain `REG_PARAMS()`, `REG_MODULE_PARAMS()` + # and `REG_MODULE_DESCRIPTION()` declarations so add to the list of + # header files to scan. + set_property(GLOBAL + APPEND + PROPERTY Z3_${component_name}_REGISTER_MODULE_HEADERS + "${_full_output_file_path}" + ) endforeach() unset(_full_include_dir_path) unset(_full_output_file_path) @@ -136,6 +160,22 @@ macro(z3_add_component component_name) endforeach() unset(_full_tactic_header_file_path) + # Add additional register module headers + foreach (extra_register_module_header ${Z3_MOD_EXTRA_REGISTER_MODULE_HEADERS}) + set(_full_extra_register_module_header_path + "${CMAKE_CURRENT_SOURCE_DIR}/${extra_register_module_header}" + ) + if (NOT (EXISTS "${_full_extra_register_module_header_path}")) + message(FATAL_ERROR "\"${_full_extra_register_module_header_path}\" does not exist") + endif() + set_property(GLOBAL + APPEND + PROPERTY Z3_${component_name}_REGISTER_MODULE_HEADERS + "${_full_extra_register_module_header_path}" + ) + endforeach() + unset(_full_extra_register_module_header) + # Using "object" libraries here means we have a convenient # name to refer to a component in CMake but we don't actually # create a static/library from them. This allows us to easily @@ -282,23 +322,27 @@ macro(z3_add_gparams_register_modules_rule) ) endif() z3_expand_dependencies(_expanded_components ${ARGN}) - # Get paths to search - set(_search_paths "") + + # Get the list of header files to parse + set(_register_module_header_files "") foreach (dependency ${_expanded_components}) - get_property(_dep_include_dirs GLOBAL PROPERTY Z3_${dependency}_INCLUDES) - list(APPEND _search_paths ${_dep_include_dirs}) + get_property(_component_register_module_header_files GLOBAL PROPERTY Z3_${dependency}_REGISTER_MODULE_HEADERS) + list(APPEND _register_module_header_files ${_component_register_module_header_files}) endforeach() - list(APPEND _search_paths "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") + unset(_component_register_module_header_files) + add_custom_command(OUTPUT "gparams_register_modules.cpp" COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/mk_gparams_register_modules_cpp.py" "${CMAKE_CURRENT_BINARY_DIR}" - ${_search_paths} + ${_register_module_header_files} DEPENDS "${CMAKE_SOURCE_DIR}/scripts/mk_gparams_register_modules_cpp.py" ${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES} - ${_expanded_components} + ${_register_module_header_files} COMMENT "Generating \"${CMAKE_CURRENT_BINARY_DIR}/gparams_register_modules.cpp\"" ${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG} VERBATIM ) + unset(_expanded_components) + unset(_register_module_header_files) endmacro() diff --git a/scripts/mk_genfile_common.py b/scripts/mk_genfile_common.py index 1a2a2dad7..1150b6333 100644 --- a/scripts/mk_genfile_common.py +++ b/scripts/mk_genfile_common.py @@ -587,7 +587,7 @@ def mk_def_file_internal(defname, dll_name, export_header_files): ############################################################################### # Functions for generating ``gparams_register_modules.cpp`` ############################################################################### -def mk_gparams_register_modules_internal(component_src_dirs, path): +def mk_gparams_register_modules_internal(h_files_full_path, path): """ Generate a ``gparams_register_modules.cpp`` file in the directory ``path``. Returns the path to the generated file. @@ -600,7 +600,7 @@ def mk_gparams_register_modules_internal(component_src_dirs, path): This procedure is invoked by gparams::init() """ - assert isinstance(component_src_dirs, list) + assert isinstance(h_files_full_path, list) assert check_dir_exists(path) cmds = [] mod_cmds = [] @@ -612,11 +612,6 @@ def mk_gparams_register_modules_internal(component_src_dirs, path): reg_pat = re.compile('[ \t]*REG_PARAMS\(\'([^\']*)\'\)') reg_mod_pat = re.compile('[ \t]*REG_MODULE_PARAMS\(\'([^\']*)\', *\'([^\']*)\'\)') reg_mod_descr_pat = re.compile('[ \t]*REG_MODULE_DESCRIPTION\(\'([^\']*)\', *\'([^\']*)\'\)') - h_files_full_path = [] - for component_src_dir in component_src_dirs: - h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(component_src_dir)) - h_files = list(map(lambda p: os.path.join(component_src_dir, p), h_files)) - h_files_full_path.extend(h_files) for h_file in sorted_headers_by_component(h_files_full_path): added_include = False with open(h_file, 'r') as fin: diff --git a/scripts/mk_gparams_register_modules_cpp.py b/scripts/mk_gparams_register_modules_cpp.py index cf6e8da96..9614768ca 100755 --- a/scripts/mk_gparams_register_modules_cpp.py +++ b/scripts/mk_gparams_register_modules_cpp.py @@ -1,10 +1,8 @@ #!/usr/bin/env python """ -Determines the available global parameters -in header files in the list of source directions -and generates a ``gparams_register_modules.cpp`` file in -the destination directory that defines a function -``void gparams_register_modules()``. +Determines the available global parameters from a list of header files and +generates a ``gparams_register_modules.cpp`` file in the destination directory +that defines a function ``void gparams_register_modules()``. """ import mk_genfile_common import argparse @@ -16,19 +14,22 @@ def main(args): logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("destination_dir", help="destination directory") - parser.add_argument("source_dirs", nargs="+", - help="One or more source directories to search") + parser.add_argument("header_files", nargs="+", + help="One or more header files to parse") pargs = parser.parse_args(args) if not mk_genfile_common.check_dir_exists(pargs.destination_dir): return 1 - for source_dir in pargs.source_dirs: - if not mk_genfile_common.check_dir_exists(source_dir): - return 1 + if not mk_genfile_common.check_files_exist(pargs.header_files): + return 1 + + h_files_full_path = [] + for header_file in pargs.header_files: + h_files_full_path.append(os.path.abspath(header_file)) output = mk_genfile_common.mk_gparams_register_modules_internal( - pargs.source_dirs, + h_files_full_path, pargs.destination_dir ) logging.info('Generated "{}"'.format(output)) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index b5924d0d1..165c27745 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2763,7 +2763,8 @@ def mk_gparams_register_modules(cnames, path): for cname in cnames: c = get_component(cname) component_src_dirs.append(c.src_dir) - generated_file = mk_genfile_common.mk_gparams_register_modules_internal(component_src_dirs, path) + h_files_full_path = get_header_files_for_components(component_src_dirs) + generated_file = mk_genfile_common.mk_gparams_register_modules_internal(h_files_full_path, path) if VERBOSE: print("Generated '{}'".format(generated_file)) diff --git a/src/ast/normal_forms/CMakeLists.txt b/src/ast/normal_forms/CMakeLists.txt index 30702cd8c..69288d92b 100644 --- a/src/ast/normal_forms/CMakeLists.txt +++ b/src/ast/normal_forms/CMakeLists.txt @@ -8,4 +8,6 @@ z3_add_component(normal_forms rewriter PYG_FILES nnf_params.pyg + EXTRA_REGISTER_MODULE_HEADERS + nnf.h ) diff --git a/src/cmd_context/CMakeLists.txt b/src/cmd_context/CMakeLists.txt index 8b2d10eec..f7b888343 100644 --- a/src/cmd_context/CMakeLists.txt +++ b/src/cmd_context/CMakeLists.txt @@ -18,4 +18,6 @@ z3_add_component(cmd_context interp rewriter solver + EXTRA_REGISTER_MODULE_HEADERS + context_params.h ) diff --git a/src/math/polynomial/CMakeLists.txt b/src/math/polynomial/CMakeLists.txt index 1d320d751..8c7d9ec02 100644 --- a/src/math/polynomial/CMakeLists.txt +++ b/src/math/polynomial/CMakeLists.txt @@ -11,5 +11,7 @@ z3_add_component(polynomial util PYG_FILES algebraic_params.pyg + EXTRA_REGISTER_MODULE_HEADERS + polynomial.h ) diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index b76f909d0..4d28fc6ad 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -59,4 +59,6 @@ z3_add_component(util util.cpp warning.cpp z3_exception.cpp + EXTRA_REGISTER_MODULE_HEADERS + env_params.h ) From d00892c9a6ffd927354dd8dd34caf08d2a16ac0f Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Wed, 21 Jun 2017 23:43:47 +0100 Subject: [PATCH 063/159] [CMake] Fix dependencies for generating `mem_initializer.cpp`. Previously CMake was not aware of which headers files the generation of `mem_initializer.cpp` depended on. Consequently this could result in broken incremental builds if * Existing headers that declare memory initializers/finalizers change. * New headers are added that declare memory initializers/finalizer. Now the `z3_add_component()` CMake function has been modifed so that it now takes an optional `MEMORY_INIT_FINALIZER_HEADERS` argument which allows the headers that declare memory initializers/finalizers to be explicitly listed. With this information CMake will now regenerate `mem_initializer.cpp` correctly. This required the `mk_mem_initializer_cpp_internal()` function to be changed to take a list of header files rather than a list of component source directories. The two consumers (CMake and Python/Makefile build systems) of this function have been modified to work with this change. This partially fixes #1030. --- cmake/z3_add_component.cmake | 40 ++++++++++++++++++++++++++++--- scripts/mk_genfile_common.py | 9 ++----- scripts/mk_mem_initializer_cpp.py | 14 +++++------ scripts/mk_util.py | 3 ++- src/util/CMakeLists.txt | 7 ++++++ 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/cmake/z3_add_component.cmake b/cmake/z3_add_component.cmake index 489dc3ee2..b70838750 100644 --- a/cmake/z3_add_component.cmake +++ b/cmake/z3_add_component.cmake @@ -57,6 +57,7 @@ endfunction() # [PYG_FILES pygfile1 [pygfile2...]] # [TACTIC_HEADERS header_file1 [header_file2...]] # [EXTRA_REGISTER_MODULE_HEADERS header_file1 [header_file2...]] +# [MEMORY_INIT_FINALIZER_HEADERS header_file1 [header_file2...]] # ) # # Declares a Z3 component (as a CMake "object library") with target name @@ -93,11 +94,15 @@ endfunction() # The optional ``EXTRA_REGISTER_MODULE_HEADERS`` keyword should be followed by a list # of one or more header files that contain module registration declarations. # NOTE: The header files generated from ``.pyg`` files don't need to be included. +# +# The optional ``MEMORY_INIT_FINALIZER_HEADERS`` keyword should be followed by a list +# of one or more header files that contain memory initializer/finalizer declarations +# (i.e. ``ADD_INITIALIZER()`` or ``ADD_FINALIZER()``). macro(z3_add_component component_name) CMAKE_PARSE_ARGUMENTS("Z3_MOD" "NOT_LIBZ3_COMPONENT" "" - "SOURCES;COMPONENT_DEPENDENCIES;PYG_FILES;TACTIC_HEADERS;EXTRA_REGISTER_MODULE_HEADERS" ${ARGN}) + "SOURCES;COMPONENT_DEPENDENCIES;PYG_FILES;TACTIC_HEADERS;EXTRA_REGISTER_MODULE_HEADERS;MEMORY_INIT_FINALIZER_HEADERS" ${ARGN}) message(STATUS "Adding component ${component_name}") # Note: We don't check the sources exist here because # they might be generated files that don't exist yet. @@ -176,6 +181,22 @@ macro(z3_add_component component_name) endforeach() unset(_full_extra_register_module_header) + # Add memory initializer/finalizer headers to global property + set_property(GLOBAL PROPERTY Z3_${component_name}_MEM_INIT_FINALIZER_HEADERS "") + foreach (memory_init_finalizer_header ${Z3_MOD_MEMORY_INIT_FINALIZER_HEADERS}) + set(_full_memory_init_finalizer_header_path + "${CMAKE_CURRENT_SOURCE_DIR}/${memory_init_finalizer_header}") + if (NOT (EXISTS "${_full_memory_init_finalizer_header_path}")) + message(FATAL_ERROR "\"${_full_memory_init_finalizer_header_path}\" does not exist") + endif() + set_property(GLOBAL + APPEND + PROPERTY Z3_${component_name}_MEM_INIT_FINALIZER_HEADERS + "${_full_memory_init_finalizer_header_path}" + ) + endforeach() + unset(_full_memory_init_finalizer_header_path) + # Using "object" libraries here means we have a convenient # name to refer to a component in CMake but we don't actually # create a static/library from them. This allows us to easily @@ -297,18 +318,31 @@ macro(z3_add_memory_initializer_rule) list(APPEND _search_paths ${_dep_include_dirs}) endforeach() list(APPEND _search_paths "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") + + # Get header files that declare initializers and finalizers + set(_mem_init_finalize_headers "") + foreach (dependency ${_expanded_components}) + get_property(_dep_mem_init_finalize_headers + GLOBAL + PROPERTY Z3_${dependency}_MEM_INIT_FINALIZER_HEADERS + ) + list(APPEND _mem_init_finalize_headers ${_dep_mem_init_finalize_headers}) + endforeach() + add_custom_command(OUTPUT "mem_initializer.cpp" COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/mk_mem_initializer_cpp.py" "${CMAKE_CURRENT_BINARY_DIR}" - ${_search_paths} + ${_mem_init_finalize_headers} DEPENDS "${CMAKE_SOURCE_DIR}/scripts/mk_mem_initializer_cpp.py" ${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES} - ${_expanded_components} + ${_mem_init_finalize_headers} COMMENT "Generating \"${CMAKE_CURRENT_BINARY_DIR}/mem_initializer.cpp\"" ${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG} VERBATIM ) + unset(_mem_init_finalize_headers) + unset(_expanded_components) endmacro() macro(z3_add_gparams_register_modules_rule) diff --git a/scripts/mk_genfile_common.py b/scripts/mk_genfile_common.py index 1150b6333..21771cc04 100644 --- a/scripts/mk_genfile_common.py +++ b/scripts/mk_genfile_common.py @@ -731,7 +731,7 @@ def mk_install_tactic_cpp_internal(h_files_full_path, path): # Functions for generating ``mem_initializer.cpp`` ############################################################################### -def mk_mem_initializer_cpp_internal(component_src_dirs, path): +def mk_mem_initializer_cpp_internal(h_files_full_path, path): """ Generate a ``mem_initializer.cpp`` file in the directory ``path``. Returns the path to the generated file. @@ -745,7 +745,7 @@ def mk_mem_initializer_cpp_internal(component_src_dirs, path): These procedures are invoked by the Z3 memory_manager """ - assert isinstance(component_src_dirs, list) + assert isinstance(h_files_full_path, list) assert check_dir_exists(path) initializer_cmds = [] finalizer_cmds = [] @@ -756,11 +756,6 @@ def mk_mem_initializer_cpp_internal(component_src_dirs, path): # ADD_INITIALIZER with priority initializer_prio_pat = re.compile('[ \t]*ADD_INITIALIZER\(\'([^\']*)\',[ \t]*(-?[0-9]*)\)') finalizer_pat = re.compile('[ \t]*ADD_FINALIZER\(\'([^\']*)\'\)') - h_files_full_path = [] - for component_src_dir in sorted(component_src_dirs): - h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(component_src_dir)) - h_files = list(map(lambda p: os.path.join(component_src_dir, p), h_files)) - h_files_full_path.extend(h_files) for h_file in sorted_headers_by_component(h_files_full_path): added_include = False with open(h_file, 'r') as fin: diff --git a/scripts/mk_mem_initializer_cpp.py b/scripts/mk_mem_initializer_cpp.py index b56fcbced..238595fa3 100755 --- a/scripts/mk_mem_initializer_cpp.py +++ b/scripts/mk_mem_initializer_cpp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python """ -Scans the source directories for +Scans the listed header files for memory initializers and finalizers and emits and implementation of ``void mem_initialize()`` and @@ -17,19 +17,19 @@ def main(args): logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("destination_dir", help="destination directory") - parser.add_argument("source_dirs", nargs="+", - help="One or more source directories to search") + parser.add_argument("header_files", nargs="+", + help="One or more header files to parse") pargs = parser.parse_args(args) if not mk_genfile_common.check_dir_exists(pargs.destination_dir): return 1 - for source_dir in pargs.source_dirs: - if not mk_genfile_common.check_dir_exists(source_dir): - return 1 + h_files_full_path = [] + for header_file in pargs.header_files: + h_files_full_path.append(os.path.abspath(header_file)) output = mk_genfile_common.mk_mem_initializer_cpp_internal( - pargs.source_dirs, + h_files_full_path, pargs.destination_dir ) logging.info('Generated "{}"'.format(output)) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 165c27745..3ce104709 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2745,7 +2745,8 @@ def mk_mem_initializer_cpp(cnames, path): for cname in cnames: c = get_component(cname) component_src_dirs.append(c.src_dir) - generated_file = mk_genfile_common.mk_mem_initializer_cpp_internal(component_src_dirs, path) + h_files_full_path = get_header_files_for_components(component_src_dirs) + generated_file = mk_genfile_common.mk_mem_initializer_cpp_internal(h_files_full_path, path) if VERBOSE: print("Generated '{}'".format(generated_file)) diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 4d28fc6ad..7ed68c89f 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -61,4 +61,11 @@ z3_add_component(util z3_exception.cpp EXTRA_REGISTER_MODULE_HEADERS env_params.h + MEMORY_INIT_FINALIZER_HEADERS + debug.h + gparams.h + prime_generator.h + rational.h + symbol.h + trace.h ) From e62e563e2de3a7ecd39d414feee9153ece150abf Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Wed, 21 Jun 2017 20:53:30 -0400 Subject: [PATCH 064/159] (mev) renamed variable to clarify that it is unused --- src/model/model_evaluator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/model/model_evaluator.cpp b/src/model/model_evaluator.cpp index 61da4b3a0..4d3092cf6 100644 --- a/src/model/model_evaluator.cpp +++ b/src/model/model_evaluator.cpp @@ -202,8 +202,8 @@ struct evaluator_cfg : public default_rewriter_cfg { void expand_value(expr_ref& val) { vector stores; expr_ref else_case(m()); - bool args_are_unique; - if (m_ar.is_array(val) && extract_array_func_interp(val, stores, else_case, args_are_unique)) { + bool _unused; + if (m_ar.is_array(val) && extract_array_func_interp(val, stores, else_case, _unused)) { sort* srt = m().get_sort(val); val = m_ar.mk_const_array(srt, else_case); for (unsigned i = stores.size(); i > 0; ) { From d5ca902bf6240a5527c15e6b0744dec87a7d274b Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Wed, 21 Jun 2017 20:54:22 -0400 Subject: [PATCH 065/159] (mev) bug fix in expanding array equalities The stores were processed in the wrong order so that (store (store a x y) x u) was reduced to (store a x y) instead of (store a x u) --- src/model/model_evaluator.cpp | 42 ++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/model/model_evaluator.cpp b/src/model/model_evaluator.cpp index 4d3092cf6..f88beba4c 100644 --- a/src/model/model_evaluator.cpp +++ b/src/model/model_evaluator.cpp @@ -213,7 +213,7 @@ struct evaluator_cfg : public default_rewriter_cfg { args.append(stores[i].size(), stores[i].c_ptr()); val = m_ar.mk_store(args.size(), args.c_ptr()); } - } + } } bool get_macro(func_decl * f, expr * & def, quantifier * & q, proof * & def_pr) { @@ -291,13 +291,13 @@ struct evaluator_cfg : public default_rewriter_cfg { else { conj.push_back(m().mk_eq(else1, else2)); } - args1.push_back(a); - args2.push_back(b); if (args_are_unique1 && args_are_unique2 && !stores1.empty()) { - return mk_array_eq(stores1, else1, stores2, else2, conj, result); + return mk_array_eq_core(stores1, else1, stores2, else2, conj, result); } // TBD: this is too inefficient. + args1.push_back(a); + args2.push_back(b); stores1.append(stores2); for (unsigned i = 0; i < stores1.size(); ++i) { args1.resize(1); args1.append(stores1[i].size() - 1, stores1[i].c_ptr()); @@ -338,20 +338,22 @@ struct evaluator_cfg : public default_rewriter_cfg { typedef hashtable args_table; - br_status mk_array_eq(vector const& stores1, expr* else1, - vector const& stores2, expr* else2, - expr_ref_vector& conj, expr_ref& result) { + br_status mk_array_eq_core(vector const& stores1, expr* else1, + vector const& stores2, expr* else2, + expr_ref_vector& conj, expr_ref& result) { unsigned arity = stores1[0].size()-1; // TBD: fix arity. args_hash ah(arity); args_eq ae(arity); args_table table1(DEFAULT_HASHTABLE_INITIAL_CAPACITY, ah, ae); args_table table2(DEFAULT_HASHTABLE_INITIAL_CAPACITY, ah, ae); - for (unsigned i = 0; i < stores1.size(); ++i) { - table1.insert(stores1[i].c_ptr()); - } - for (unsigned i = stores2.size(); i > 0; ) { + // stores with smaller index take precedence + for (unsigned i = stores1.size(); i > 0; ) { --i; + table1.insert(stores1[i].c_ptr()); + } + + for (unsigned i = 0, sz = stores2.size(); i < sz; ++i) { if (table2.contains(stores2[i].c_ptr())) { // first insertion takes precedence. continue; @@ -361,7 +363,7 @@ struct evaluator_cfg : public default_rewriter_cfg { expr* val = stores2[i][arity]; if (table1.find(stores2[i].c_ptr(), args)) { switch (compare(args[arity], val)) { - case l_true: table1.remove(stores2[i].c_ptr()); break; + case l_true: table1.remove(args); break; case l_false: result = m().mk_false(); return BR_DONE; default: conj.push_back(m().mk_eq(val, args[arity])); break; } @@ -389,10 +391,10 @@ struct evaluator_cfg : public default_rewriter_cfg { lbool compare(expr* a, expr* b) { if (m().are_equal(a, b)) return l_true; if (m().are_distinct(a, b)) return l_false; - return l_undef; + return l_undef; } - + bool args_are_values(expr_ref_vector const& store, bool& are_unique) { bool are_values = true; for (unsigned j = 0; are_values && j + 1 < store.size(); ++j) { @@ -402,7 +404,7 @@ struct evaluator_cfg : public default_rewriter_cfg { SASSERT(!are_unique || are_values); return are_values; } - + bool extract_array_func_interp(expr* a, vector& stores, expr_ref& else_case, bool& are_unique) { SASSERT(m_ar.is_array(a)); @@ -417,14 +419,14 @@ struct evaluator_cfg : public default_rewriter_cfg { stores.push_back(store); a = to_app(a)->get_arg(0); } - + if (m_ar.is_const(a)) { else_case = to_app(a)->get_arg(0); return true; } - + if (!m_ar.is_as_array(a)) { - TRACE("model_evaluator", tout << "no translation: " << mk_pp(a, m()) << "\n";); + TRACE("model_evaluator", tout << "no translation: " << mk_pp(a, m()) << "\n";); return false; } @@ -444,7 +446,7 @@ struct evaluator_cfg : public default_rewriter_cfg { } } stores.push_back(store); - } + } else_case = g->get_else(); if (!else_case) { TRACE("model_evaluator", tout << "no else case " << mk_pp(a, m()) << "\n"; @@ -524,7 +526,7 @@ unsigned model_evaluator::get_num_steps() const { void model_evaluator::cleanup(params_ref const & p) { model_core & md = m_imp->cfg().m_model; dealloc(m_imp); - m_imp = alloc(imp, md, p); + m_imp = alloc(imp, md, p); } void model_evaluator::reset(params_ref const & p) { From 493a3a63125230cc567380543d6679c749334e15 Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Tue, 20 Jun 2017 23:39:38 -0400 Subject: [PATCH 066/159] (mev) call expand_value only at the end There is no need to expand array values throughout evaluation. They are expanded during array equality checking (if requested), and can be expanded at the very end of evaluation (if needed). --- src/model/model_evaluator.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/model/model_evaluator.cpp b/src/model/model_evaluator.cpp index f88beba4c..279cfde3b 100644 --- a/src/model/model_evaluator.cpp +++ b/src/model/model_evaluator.cpp @@ -125,7 +125,6 @@ struct evaluator_cfg : public default_rewriter_cfg { expr * val = m_model.get_const_interp(f); if (val != 0) { result = val; - expand_value(result); return BR_DONE; } @@ -274,7 +273,6 @@ struct evaluator_cfg : public default_rewriter_cfg { return BR_FAILED; } - // disabled until made more efficient vector stores1, stores2; bool args_are_unique1, args_are_unique2; expr_ref else1(m()), else2(m()); @@ -489,6 +487,10 @@ struct model_evaluator::imp : public rewriter_tpl { m_cfg(md.get_manager(), md, p) { set_cancel_check(false); } + + void expand_value (expr_ref &val) { + m_cfg.expand_value (val); + } }; model_evaluator::model_evaluator(model_core & md, params_ref const & p) { @@ -537,14 +539,12 @@ void model_evaluator::reset(params_ref const & p) { void model_evaluator::operator()(expr * t, expr_ref & result) { TRACE("model_evaluator", tout << mk_ismt2_pp(t, m()) << "\n";); m_imp->operator()(t, result); + m_imp->expand_value(result); } expr_ref model_evaluator::operator()(expr * t) { TRACE("model_evaluator", tout << mk_ismt2_pp(t, m()) << "\n";); expr_ref result(m()); - m_imp->operator()(t, result); + this->operator()(t, result); return result; } - - - From 2d49119d2ab112f43b94b5f561771bed4ca126c6 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 21 Jun 2017 18:55:35 -0700 Subject: [PATCH 067/159] add note to Context documentation about scoped uses of contexts #1077 --- src/api/java/Context.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/api/java/Context.java b/src/api/java/Context.java index db7a08711..2609dbb29 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -25,6 +25,12 @@ import java.util.Map; /** * The main interaction with Z3 happens via the Context. + * For applications that spawn an unbounded number of contexts, + * the proper use is within a try-with-resources + * scope so that the Context object gets garbage collected in + * a predictable way. Contexts maintain all data-structures + * related to terms and formulas that are created relative + * to them. **/ public class Context implements AutoCloseable { private final long m_ctx; From 972ab6298cde5cdeade5d7f456e9738fe2c8dd6b Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Wed, 21 Jun 2017 22:59:52 -0400 Subject: [PATCH 068/159] (mev) only reduce function interpretation --- src/model/model_evaluator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/model/model_evaluator.cpp b/src/model/model_evaluator.cpp index 279cfde3b..805ed8e5d 100644 --- a/src/model/model_evaluator.cpp +++ b/src/model/model_evaluator.cpp @@ -432,6 +432,7 @@ struct evaluator_cfg : public default_rewriter_cfg { func_interp* g = m_model.get_func_interp(f); unsigned sz = g->num_entries(); unsigned arity = f->get_arity(); + unsigned base_sz = stores.size(); for (unsigned i = 0; i < sz; ++i) { expr_ref_vector store(m()); func_entry const* fe = g->get_entry(i); @@ -456,7 +457,7 @@ struct evaluator_cfg : public default_rewriter_cfg { TRACE("model_evaluator", tout << "non-ground else case " << mk_pp(a, m()) << "\n" << else_case << "\n";); return false; } - for (unsigned i = stores.size(); are_values && i > 0; ) { + for (unsigned i = stores.size(); are_values && i > base_sz; ) { --i; if (m().are_equal(else_case, stores[i].back())) { for (unsigned j = i + 1; j < stores.size(); ++j) { From ed038c2a107854d64d292406b32b34d608818cdd Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Thu, 22 Jun 2017 09:42:22 +0100 Subject: [PATCH 069/159] [CMake] Fix CMake warning about CMP0042 on macOS --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ed7ee06a..6f39cac13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,11 @@ if (POLICY CMP0054) cmake_policy(SET CMP0054 OLD) endif() +if (POLICY CMP0042) + # Enable `MACOSX_RPATH` by default. + cmake_policy(SET CMP0042 NEW) +endif() + set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake") project(Z3 CXX) From 2a5f1d6e93d032172f3ea4f505e4f192a8652c5f Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 22 Jun 2017 10:32:35 -0700 Subject: [PATCH 070/159] add a template instantination Signed-off-by: Lev Nachmanson --- src/util/lp/dense_matrix_instances.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/lp/dense_matrix_instances.cpp b/src/util/lp/dense_matrix_instances.cpp index 1e931211d..95ba01801 100644 --- a/src/util/lp/dense_matrix_instances.cpp +++ b/src/util/lp/dense_matrix_instances.cpp @@ -11,6 +11,7 @@ template void lean::dense_matrix::apply_from_left(vector template lean::dense_matrix::dense_matrix(lean::matrix const*); template lean::dense_matrix::dense_matrix(unsigned int, unsigned int); template lean::dense_matrix& lean::dense_matrix::operator=(lean::dense_matrix const&); +template lean::dense_matrix::dense_matrix(unsigned int, unsigned int); template lean::dense_matrix >::dense_matrix(lean::matrix > const*); template void lean::dense_matrix >::apply_from_left(vector&); template lean::dense_matrix lean::operator*(lean::matrix&, lean::matrix&); From 7386f2e04535485c92733aab76290e26c3c45741 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 22 Jun 2017 14:18:53 -0700 Subject: [PATCH 071/159] #1101 Signed-off-by: Nikolaj Bjorner --- src/opt/opt_context.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/opt/opt_context.cpp b/src/opt/opt_context.cpp index 54909939f..0e1c150c0 100644 --- a/src/opt/opt_context.cpp +++ b/src/opt/opt_context.cpp @@ -1313,17 +1313,18 @@ namespace opt { rational r = n.get_rational(); rational eps = n.get_infinitesimal(); expr_ref_vector args(m); + bool is_int = eps.is_zero() && r.is_int(); if (!inf.is_zero()) { - expr* oo = m.mk_const(symbol("oo"), m_arith.mk_int()); + expr* oo = m.mk_const(symbol("oo"), is_int ? m_arith.mk_int() : m_arith.mk_real()); if (inf.is_one()) { args.push_back(oo); } else { - args.push_back(m_arith.mk_mul(m_arith.mk_numeral(inf, inf.is_int()), oo)); + args.push_back(m_arith.mk_mul(m_arith.mk_numeral(inf, is_int), oo)); } } if (!r.is_zero()) { - args.push_back(m_arith.mk_numeral(r, r.is_int())); + args.push_back(m_arith.mk_numeral(r, is_int)); } if (!eps.is_zero()) { expr* ep = m.mk_const(symbol("epsilon"), m_arith.mk_real()); @@ -1331,7 +1332,7 @@ namespace opt { args.push_back(ep); } else { - args.push_back(m_arith.mk_mul(m_arith.mk_numeral(eps, eps.is_int()), ep)); + args.push_back(m_arith.mk_mul(m_arith.mk_numeral(eps, is_int), ep)); } } switch(args.size()) { From 9874db7458ddcda1375aedb9237a176f95e2c818 Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Fri, 23 Jun 2017 09:36:09 -0400 Subject: [PATCH 072/159] [CMake] typos in cmake --- src/api/CMakeLists.txt | 2 +- src/ast/pattern/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/CMakeLists.txt b/src/api/CMakeLists.txt index 8e796168f..79c5fc1c9 100644 --- a/src/api/CMakeLists.txt +++ b/src/api/CMakeLists.txt @@ -7,7 +7,7 @@ set(generated_files # Sanity check foreach (gen_file ${generated_files}) if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${gen_file}") - message(FATAL_ERROR "\"${CMAKE_CURRENT_SOURCE_DIR}/${gen_files}\"" + message(FATAL_ERROR "\"${CMAKE_CURRENT_SOURCE_DIR}/${gen_file}\"" ${z3_polluted_tree_msg}) endif() endforeach() diff --git a/src/ast/pattern/CMakeLists.txt b/src/ast/pattern/CMakeLists.txt index 59e0545a1..6e8301afc 100644 --- a/src/ast/pattern/CMakeLists.txt +++ b/src/ast/pattern/CMakeLists.txt @@ -2,7 +2,7 @@ # for other components then we should refactor this code into # z3_add_component() if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/database.h") - message(FATAL_ERROR "The generated file \"database.h\"" + message(FATAL_ERROR "The generated file \"${CMAKE_CURRENT_SOURCE_DIR}/database.h\"" ${z3_polluted_tree_msg}) endif() From 0dead22dca50d07207e0fd816be4b3e441cdb0b1 Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Fri, 23 Jun 2017 09:36:44 -0400 Subject: [PATCH 073/159] fix missing initialization --- src/muz/transforms/dl_mk_quantifier_abstraction.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/muz/transforms/dl_mk_quantifier_abstraction.cpp b/src/muz/transforms/dl_mk_quantifier_abstraction.cpp index 5c0d442df..a22a67416 100644 --- a/src/muz/transforms/dl_mk_quantifier_abstraction.cpp +++ b/src/muz/transforms/dl_mk_quantifier_abstraction.cpp @@ -142,7 +142,8 @@ namespace datalog { m(ctx.get_manager()), m_ctx(ctx), a(m), - m_refs(m) { + m_refs(m), + m_mc(NULL){ } mk_quantifier_abstraction::~mk_quantifier_abstraction() { From c7fbab0c1160b069a2f6458e621a2f04185a7d8a Mon Sep 17 00:00:00 2001 From: Arie Gurfinkel Date: Fri, 23 Jun 2017 09:37:19 -0400 Subject: [PATCH 074/159] propagate rule names during xform --- src/muz/rel/dl_mk_similarity_compressor.cpp | 2 +- src/muz/rel/dl_mk_simple_joins.cpp | 2 +- src/muz/transforms/dl_mk_slice.cpp | 2 +- src/muz/transforms/dl_mk_unbound_compressor.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/muz/rel/dl_mk_similarity_compressor.cpp b/src/muz/rel/dl_mk_similarity_compressor.cpp index 75caba6ae..b65ed455c 100644 --- a/src/muz/rel/dl_mk_similarity_compressor.cpp +++ b/src/muz/rel/dl_mk_similarity_compressor.cpp @@ -426,7 +426,7 @@ namespace datalog { new_negs.push_back(false); rule * new_rule = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), - new_negs.c_ptr()); + new_negs.c_ptr(), r->name()); m_result_rules.push_back(new_rule); //TODO: allow for a rule to have multiple parent objects diff --git a/src/muz/rel/dl_mk_simple_joins.cpp b/src/muz/rel/dl_mk_simple_joins.cpp index e428fdd2e..a8e54085d 100644 --- a/src/muz/rel/dl_mk_simple_joins.cpp +++ b/src/muz/rel/dl_mk_simple_joins.cpp @@ -726,7 +726,7 @@ namespace datalog { } rule * new_rule = m_context.get_rule_manager().mk(orig_r->get_head(), tail.size(), tail.c_ptr(), - negs.c_ptr()); + negs.c_ptr(), orig_r->name()); new_rule->set_accounting_parent_object(m_context, orig_r); m_context.get_rule_manager().mk_rule_rewrite_proof(*orig_r, *new_rule); diff --git a/src/muz/transforms/dl_mk_slice.cpp b/src/muz/transforms/dl_mk_slice.cpp index aa910002d..cefda74e8 100644 --- a/src/muz/transforms/dl_mk_slice.cpp +++ b/src/muz/transforms/dl_mk_slice.cpp @@ -789,7 +789,7 @@ namespace datalog { tail.push_back(to_app(e)); } - new_rule = rm.mk(head.get(), tail.size(), tail.c_ptr(), (const bool*) 0); + new_rule = rm.mk(head.get(), tail.size(), tail.c_ptr(), (const bool*) 0, r.name()); rm.fix_unbound_vars(new_rule, false); diff --git a/src/muz/transforms/dl_mk_unbound_compressor.cpp b/src/muz/transforms/dl_mk_unbound_compressor.cpp index 41b181450..78133aab7 100644 --- a/src/muz/transforms/dl_mk_unbound_compressor.cpp +++ b/src/muz/transforms/dl_mk_unbound_compressor.cpp @@ -173,7 +173,7 @@ namespace datalog { return l_false; } else { - rule_ref new_rule(m_context.get_rule_manager().mk(r, chead), m_context.get_rule_manager()); + rule_ref new_rule(m_context.get_rule_manager().mk(r, chead, r->name()), m_context.get_rule_manager()); new_rule->set_accounting_parent_object(m_context, r); m_head_occurrence_ctr.dec(m_rules.get(rule_index)->get_decl()); From cd4bb5beaf723f2bf0359aaef5076542b251990d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 23 Jun 2017 11:34:10 -0700 Subject: [PATCH 075/159] another fix for #1101 Signed-off-by: Nikolaj Bjorner --- src/smt/theory_lra.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index a5a34a079..76e721faa 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -2386,16 +2386,16 @@ namespace smt { app_ref mk_obj(theory_var v) { lean::var_index vi = m_theory_var2var_index[v]; + bool is_int = a.is_int(get_enode(v)->get_owner()); if (m_solver->is_term(vi)) { expr_ref_vector args(m); const lean::lar_term& term = m_solver->get_term(vi); for (auto & ti : term.m_coeffs) { theory_var w = m_var_index2theory_var[ti.first]; expr* o = get_enode(w)->get_owner(); - args.push_back(a.mk_mul(a.mk_numeral(ti.second, a.is_int(o)), o)); + args.push_back(a.mk_mul(a.mk_numeral(ti.second, is_int), o)); } - rational r = term.m_v; - args.push_back(a.mk_numeral(r, r.is_int())); + args.push_back(a.mk_numeral(term.m_v, is_int)); return app_ref(a.mk_add(args.size(), args.c_ptr()), m); } else { @@ -2408,11 +2408,12 @@ namespace smt { rational r = val.get_rational(); bool is_strict = val.get_infinitesimal().is_pos(); app_ref b(m); + bool is_int = a.is_int(get_enode(v)->get_owner()); if (is_strict) { - b = a.mk_le(mk_obj(v), a.mk_numeral(r, r.is_int())); + b = a.mk_le(mk_obj(v), a.mk_numeral(r, is_int)); } else { - b = a.mk_ge(mk_obj(v), a.mk_numeral(r, r.is_int())); + b = a.mk_ge(mk_obj(v), a.mk_numeral(r, is_int)); } if (!ctx().b_internalized(b)) { fm.insert(b->get_decl()); From 9d1852343c47ca6abd05752a60650f521bf399e4 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 23 Jun 2017 16:34:38 -0700 Subject: [PATCH 076/159] add separate get-objectives command #1107 Signed-off-by: Nikolaj Bjorner --- src/cmd_context/cmd_context.cpp | 3 +-- src/opt/opt_cmds.cpp | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index af16f5796..d252c3629 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -1360,7 +1360,6 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions throw ex; } catch (z3_exception & ex) { - get_opt()->display_assignment(regular_stream()); throw cmd_exception(ex.msg()); } if (m_processing_pareto && r != l_true) { @@ -1398,7 +1397,7 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions } validate_check_sat_result(r); if (was_opt && r != l_false && !m_processing_pareto) { - get_opt()->display_assignment(regular_stream()); + // get_opt()->display_assignment(regular_stream()); } if (r == l_true && m_params.m_dump_models) { diff --git a/src/opt/opt_cmds.cpp b/src/opt/opt_cmds.cpp index a5c163562..0264a6a24 100644 --- a/src/opt/opt_cmds.cpp +++ b/src/opt/opt_cmds.cpp @@ -143,12 +143,35 @@ public: } }; +class get_objectives_cmd : public cmd { + opt::context* m_opt; +public: + get_objectives_cmd(opt::context* opt): + cmd("get-objectives"), + m_opt(opt) + {} + + virtual void reset(cmd_context & ctx) { } + virtual char const * get_usage() const { return "(get-objectives)"; } + virtual char const * get_descr(cmd_context & ctx) const { return "retrieve the objective values (after optimization)"; } + virtual unsigned get_arity() const { return 0; } + virtual void prepare(cmd_context & ctx) {} + virtual void failure_cleanup(cmd_context & ctx) { + reset(ctx); + } + + virtual void execute(cmd_context & ctx) { + get_opt(ctx, m_opt).display_assignment(ctx.regular_stream()); + } +}; + void install_opt_cmds(cmd_context & ctx, opt::context* opt) { ctx.insert(alloc(assert_soft_cmd, opt)); ctx.insert(alloc(min_maximize_cmd, true, opt)); ctx.insert(alloc(min_maximize_cmd, false, opt)); + ctx.insert(alloc(get_objectives_cmd, opt)); } From 1681419052d156240b76c4e85b5750b82ecc6a88 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 23 Jun 2017 16:50:33 -0700 Subject: [PATCH 077/159] adding change notes to release notes for a future release Signed-off-by: Nikolaj Bjorner --- RELEASE_NOTES | 10 ++++++++++ src/smt/smt_context.cpp | 8 +++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 357c17e78..ec05160da 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,5 +1,15 @@ RELEASE NOTES +Version 4.5.x +============= +- New features (including): + - A new string solver from University of Waterloo + - A new linear real arithmetic solver + - Changed behavior for optimization commands from the SMT2 command-line interface. + Objective values are no longer printed by default. They can be retrieved by + issuing the command (get-objectives). Pareto front objectives are accessed by + issuing multiple (check-sat) calls until it returns unsat. + Version 4.5.0 ============= diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 0c32f3c76..4e56d3004 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -4332,10 +4332,9 @@ namespace smt { ); failure fl = get_last_search_failure(); if (fl == MEMOUT || fl == CANCELED || fl == TIMEOUT || fl == NUM_CONFLICTS || fl == RESOURCE_LIMIT) { - return; + TRACE("get_model", tout << "last search failure: " << fl << "\n";); } - - if (m_fparams.m_model || m_fparams.m_model_on_final_check || m_qmanager->model_based()) { + else if (m_fparams.m_model || m_fparams.m_model_on_final_check || m_qmanager->model_based()) { m_model_generator->reset(); m_proto_model = m_model_generator->mk_model(); m_qmanager->adjust_model(m_proto_model.get()); @@ -4346,6 +4345,9 @@ namespace smt { if (m_fparams.m_model_compact) m_proto_model->compress(); TRACE("mbqi_bug", tout << "after cleanup:\n"; model_pp(tout, *m_proto_model);); + } + else { + } } From 1631a68981d6905c0e0763e4bf143628e0c0b86d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 23 Jun 2017 16:57:50 -0700 Subject: [PATCH 078/159] make the option soup dependencies more user-friendly, #1109 Signed-off-by: Nikolaj Bjorner --- src/smt/tactic/smt_tactic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smt/tactic/smt_tactic.cpp b/src/smt/tactic/smt_tactic.cpp index 9e3eddafa..64bae0a48 100644 --- a/src/smt/tactic/smt_tactic.cpp +++ b/src/smt/tactic/smt_tactic.cpp @@ -253,7 +253,7 @@ public: if (m_ctx->canceled()) { throw tactic_exception(Z3_CANCELED_MSG); } - if (m_fail_if_inconclusive) { + if (m_fail_if_inconclusive && !m_candidate_models) { std::stringstream strm; strm << "smt tactic failed to show goal to be sat/unsat " << m_ctx->last_failure_as_string(); throw tactic_exception(strm.str().c_str()); From ae8a089e254a5820f00aa7dfb611bd3d6c9c7028 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Sat, 24 Jun 2017 13:47:51 +0100 Subject: [PATCH 079/159] [CMake] Fix missing sanitization in `z3_add_cxx_flag flag()` function which caused CMake 2.8.12 to hit an error when handling the `-std=c++11` flag. --- cmake/z3_add_cxx_flag.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/z3_add_cxx_flag.cmake b/cmake/z3_add_cxx_flag.cmake index 8bffd7de3..6e756d3b9 100644 --- a/cmake/z3_add_cxx_flag.cmake +++ b/cmake/z3_add_cxx_flag.cmake @@ -8,6 +8,7 @@ function(z3_add_cxx_flag flag) string(REPLACE "=" "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}") string(REPLACE " " "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}") string(REPLACE ":" "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}") + string(REPLACE "+" "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}") unset(HAS_${SANITIZED_FLAG_NAME}) CHECK_CXX_COMPILER_FLAG("${flag}" HAS_${SANITIZED_FLAG_NAME}) if (z3_add_flag_REQUIRED AND NOT HAS_${SANITIZED_FLAG_NAME}) From 5a8205cb0cc4a8c6f1293b11a5a68b3fa98a2c10 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Sat, 24 Jun 2017 14:05:25 +0100 Subject: [PATCH 080/159] [CMake] Unbreak detection of pthreads for CMake versions < 3.4 --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f39cac13..971ea9cbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,13 @@ endif() set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake") project(Z3 CXX) +if ("${CMAKE_VERSION}" VERSION_LESS "3.4") + # FIXME: Drop this when we upgrade to newer CMake versions. + # HACK: Although we don't need C language support if it is not + # enabled CMake's `FindThreads` module fails in old CMake versions. + enable_language(C) +endif() + ################################################################################ # Project version ################################################################################ From 489077a3eb800b74605c965fa3c152fecf257110 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Sat, 24 Jun 2017 14:16:48 +0100 Subject: [PATCH 081/159] [CMake] Remove use of `INSTALL_PREFIX` argument to `configure_package_config_file()`. This argument wasn't available until CMake 3.1 and we don't appear to be really using it anyway. --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 971ea9cbd..bf894a5c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -540,7 +540,6 @@ configure_package_config_file("${CMAKE_SOURCE_DIR}/cmake/Z3Config.cmake.in" Z3_FIRST_PACKAGE_INCLUDE_DIR Z3_SECOND_PACKAGE_INCLUDE_DIR Z3_CXX_PACKAGE_INCLUDE_DIR - INSTALL_PREFIX "${CMAKE_BINARY_DIR}" ) unset(Z3_FIRST_PACKAGE_INCLUDE_DIR) unset(Z3_SECOND_PACKAGE_INCLUDE_DIR) From 3229bedb36dd8d4ab6f6a809709c2270fbe0d83d Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Sat, 24 Jun 2017 14:41:33 +0100 Subject: [PATCH 082/159] [CMake] Unbreak the configure step for CMake 2.8.12 --- CMakeLists.txt | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf894a5c9..8ed5c7d5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -524,10 +524,18 @@ add_subdirectory(src) # use Z3 via CMake. ################################################################################ include(CMakePackageConfigHelpers) -export(EXPORT Z3_EXPORTED_TARGETS - NAMESPACE z3:: - FILE "${CMAKE_BINARY_DIR}/Z3Targets.cmake" -) +if ("${CMAKE_VERSION}" VERSION_LESS "3.0") + # FIXME: Remove this once we drop support for CMake 2.8.12 + export(TARGETS libz3 + NAMESPACE z3:: + FILE "${CMAKE_BINARY_DIR}/Z3Targets.cmake" + ) +else() + export(EXPORT Z3_EXPORTED_TARGETS + NAMESPACE z3:: + FILE "${CMAKE_BINARY_DIR}/Z3Targets.cmake" + ) +endif() set(Z3_FIRST_PACKAGE_INCLUDE_DIR "${CMAKE_BINARY_DIR}/src/api") set(Z3_SECOND_PACKAGE_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/src/api") set(Z3_CXX_PACKAGE_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/src/api/c++") From 80c0c4f66362d7815e6062c391be2d68b80a6f11 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Sat, 24 Jun 2017 15:15:27 +0100 Subject: [PATCH 083/159] [CMake] Fix detection of git description and hash for CMake 2.8.12 --- CMakeLists.txt | 4 ++-- cmake/git_utils.cmake | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ed5c7d5e..c8ecb5295 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,7 +109,7 @@ if (EXISTS "${GIT_DIR}") endif() message(STATUS "Using Git hash in version output: ${Z3GITHASH}") # This mimics the behaviour of the old build system. - string(APPEND Z3_FULL_VERSION_STR " ${Z3GITHASH}") + set(Z3_FULL_VERSION_STR "${Z3_FULL_VERSION_STR} ${Z3GITHASH}") else() message(STATUS "Not using Git hash in version output") unset(Z3GITHASH) # Used in configure_file() @@ -122,7 +122,7 @@ if (EXISTS "${GIT_DIR}") endif() message(STATUS "Using Git description in version output: ${Z3_GIT_DESCRIPTION}") # This mimics the behaviour of the old build system. - string(APPEND Z3_FULL_VERSION_STR " ${Z3_GIT_DESCRIPTION}") + set(Z3_FULL_VERSION_STR "${Z3_FULL_VERSION_STR} ${Z3_GIT_DESCRIPTION}") else() message(STATUS "Not including git descrption in version") endif() diff --git a/cmake/git_utils.cmake b/cmake/git_utils.cmake index aa7f38825..f98aca205 100644 --- a/cmake/git_utils.cmake +++ b/cmake/git_utils.cmake @@ -99,7 +99,9 @@ function(get_git_head_hash GIT_DIR OUTPUT_VAR) message(FATAL_ERROR \""${GIT_DIR}\" is not an absolute path") endif() find_package(Git) - if (NOT Git_FOUND) + # NOTE: Use `GIT_FOUND` rather than `Git_FOUND` which was only + # available in CMake >= 3.5 + if (NOT GIT_FOUND) set(${OUTPUT_VAR} "GIT-NOTFOUND" PARENT_SCOPE) return() endif() @@ -146,7 +148,9 @@ function(get_git_head_describe GIT_DIR OUTPUT_VAR) message(FATAL_ERROR \""${GIT_DIR}\" is not an absolute path") endif() find_package(Git) - if (NOT Git_FOUND) + # NOTE: Use `GIT_FOUND` rather than `Git_FOUND` which was only + # available in CMake >= 3.5 + if (NOT GIT_FOUND) set(${OUTPUT_VAR} "GIT-NOTFOUND" PARENT_SCOPE) return() endif() From ad7aff2334eee9d73198f196549d0d1bb14a9c11 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 25 Jun 2017 20:45:56 +0100 Subject: [PATCH 084/159] Added rlimit increments in theory_arith to avoid non-termination issues via F*. --- src/smt/theory_arith_core.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index 5c652414a..ae015c08f 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -1716,7 +1716,7 @@ namespace smt { CASSERT("arith", check_null_var_pos()); r1.save_var_pos(m_var_pos); - + // // loop over variables in row2, // add terms in row2 to row1. @@ -1769,7 +1769,7 @@ namespace smt { ADD_ROW(r_entry.m_coeff = it->m_coeff; r_entry.m_coeff *= coeff, r_entry.m_coeff += it->m_coeff * coeff); } - + r1.reset_var_pos(m_var_pos); CASSERT("arith", check_null_var_pos()); CASSERT("row_assignment_bug", valid_row_assignment(r1)); @@ -1778,7 +1778,7 @@ namespace smt { theory_var v = r1.get_base_var(); if (is_int(v) && !get_value(v).is_int()) gcd_test(r1); - } + } } /** @@ -1797,6 +1797,7 @@ namespace smt { SASSERT(!is_non_base(v)); add_row(r1, c, get_var_row(v), false); } + get_manager().limit().inc(sz); } // ----------------------------------- @@ -1852,6 +1853,7 @@ namespace smt { if (is_base(v) && !m_to_patch.contains(v) && (below_lower(v) || above_upper(v))) { m_to_patch.insert(v); } + get_manager().limit().inc(); } /** @@ -1928,6 +1930,8 @@ namespace smt { DIVIDE_ROW(it->m_coeff /= tmp); } + get_manager().limit().inc(r.size()); + set_var_row(x_i, -1); set_var_row(x_j, r_id); @@ -1937,7 +1941,7 @@ namespace smt { set_var_kind(x_i, NON_BASE); set_var_kind(x_j, BASE); - eliminate(x_j, apply_gcd_test); + eliminate(x_j, apply_gcd_test); CASSERT("arith", wf_rows()); CASSERT("arith", wf_columns()); @@ -1972,6 +1976,7 @@ namespace smt { int s_pos = -1; for (; it != end; ++it, ++i) { if (!it->is_dead()) { + unsigned r1_sz = m_rows[r_id].size(); if (it->m_row_id != static_cast(r_id)) { row & r2 = m_rows[it->m_row_id]; theory_var s2 = r2.m_base_var; @@ -1979,13 +1984,14 @@ namespace smt { a_kj = r2[it->m_row_idx].m_coeff; a_kj.neg(); add_row(it->m_row_id, a_kj, r_id, apply_gcd_test); + get_manager().limit().inc(r1_sz + r2.size()); } } else { s_pos = i; } } - } + } CTRACE("eliminate", !Lazy && c.size() != 1, tout << "eliminating v" << x_i << ", Lazy: " << Lazy << ", c.size: " << c.size() << "\n"; display(tout);); From c395516058f5d0c756c892066d07cb074b415140 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 25 Jun 2017 22:19:42 +0100 Subject: [PATCH 085/159] Adjusted rlimit increments in theory_arith to avoid non-termination issues --- src/smt/theory_arith_core.h | 2 +- src/util/mpq.h | 4 +++- src/util/mpz.h | 4 ++-- src/util/rational.h | 2 ++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index ae015c08f..bee744c34 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -1984,7 +1984,7 @@ namespace smt { a_kj = r2[it->m_row_idx].m_coeff; a_kj.neg(); add_row(it->m_row_id, a_kj, r_id, apply_gcd_test); - get_manager().limit().inc(r1_sz + r2.size()); + get_manager().limit().inc((r1_sz + r2.size()) * (a_kj.storage_size())); } } else { diff --git a/src/util/mpq.h b/src/util/mpq.h index 474d38802..11e17bbf9 100644 --- a/src/util/mpq.h +++ b/src/util/mpq.h @@ -176,7 +176,7 @@ public: static bool is_small(mpz const & a) { return mpz_manager::is_small(a); } - static bool is_small(mpq const & a) { return is_small(a.m_num) && is_small(a.m_den); } + static bool is_small(mpq const & a) { return is_small(a.m_num) && is_small(a.m_den); } static mpq mk_q(int v) { return mpq(v); } @@ -786,6 +786,8 @@ public: unsigned bitsize(mpz const & a) { return mpz_manager::bitsize(a); } unsigned bitsize(mpq const & a) { return is_int(a) ? bitsize(a.m_num) : bitsize(a.m_num) + bitsize(a.m_den); } + unsigned storage_size(mpz const & a) { return mpz_manager::size_info(a); } + unsigned storage_size(mpq const & a) { return mpz_manager::size_info(a.m_num) + mpz_manager::size_info(a.m_den); } /** \brief Return true if the number is a perfect square, and diff --git a/src/util/mpz.h b/src/util/mpz.h index 67947b602..c02ac7c36 100644 --- a/src/util/mpz.h +++ b/src/util/mpz.h @@ -316,11 +316,11 @@ class mpz_manager { void big_rem(mpz const & a, mpz const & b, mpz & c); int big_compare(mpz const & a, mpz const & b); - + +public: unsigned size_info(mpz const & a); struct sz_lt; -public: static bool precise() { return true; } static bool field() { return false; } diff --git a/src/util/rational.h b/src/util/rational.h index 4fa3382ec..26ef7dbb1 100644 --- a/src/util/rational.h +++ b/src/util/rational.h @@ -68,6 +68,8 @@ public: mpq const & to_mpq() const { return m_val; } unsigned bitsize() const { return m().bitsize(m_val); } + + unsigned storage_size() const { return m().storage_size(m_val); } void reset() { m().reset(m_val); } From 42e0f8f9ce65e659845276271773bcb266a51d25 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Sun, 25 Jun 2017 22:57:13 +0100 Subject: [PATCH 086/159] Unbreak Z3 C++ API exception support for GCC < 5.0. This was broken by 0b1d5645097d41eec4c43946407e08d57b41ad64 . Older versions of GCC do not define `__cpp_exceptions` which caused exceptions to not be raised leading to unexpected failures. To fix this also check the `__EXCEPTIONS` macro which is used by older GCC versions. Also `#undef` the `Z3_THROW` macro at the end of the header file because this is an implementation detail that we don't want to leak to clients. --- src/api/c++/z3++.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index 9d9982523..42db6f352 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -87,7 +87,7 @@ namespace z3 { inline std::ostream & operator<<(std::ostream & out, exception const & e) { out << e.msg(); return out; } #if !defined(Z3_THROW) -#if __cpp_exceptions || _CPPUNWIND +#if __cpp_exceptions || _CPPUNWIND || __EXCEPTIONS #define Z3_THROW(x) throw x #else #define Z3_THROW(x) {} @@ -2796,6 +2796,6 @@ namespace z3 { /*@}*/ /*@}*/ - +#undef Z3_THROW #endif From 849eb389e6be734f12523f83e583776c52a7013e Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Sun, 25 Jun 2017 23:08:24 +0100 Subject: [PATCH 087/159] [CMake] Add missing python example files. We have to flatten the hierarchy when copying across so that all Python examples have the `z3` directory in their directory. --- examples/python/CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/examples/python/CMakeLists.txt b/examples/python/CMakeLists.txt index fdbb7891f..9bd45df41 100644 --- a/examples/python/CMakeLists.txt +++ b/examples/python/CMakeLists.txt @@ -1,5 +1,11 @@ set(python_example_files + all_interval_series.py + complex/complex.py example.py + hamiltonian/hamiltonian.py + mus/marco.py + mus/mss.py + socrates.py visitor.py ) @@ -10,7 +16,10 @@ foreach (example_file ${python_example_files}) add_custom_command(OUTPUT "${z3py_bindings_build_dest}/${example_file}" COMMAND "${CMAKE_COMMAND}" "-E" "copy" "${CMAKE_CURRENT_SOURCE_DIR}/${example_file}" - "${z3py_bindings_build_dest}/${example_file}" + # We flatten the hierarchy so that all python files have + # the `z3` directory in their directory so that their import + # statements "just work". + "${z3py_bindings_build_dest}/" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${example_file}" COMMENT "Copying \"${example_file}\" to ${z3py_bindings_build_dest}/${example_file}" ) From 896aae5606269723cc2356fd09803e9d0d0ded59 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Mon, 26 Jun 2017 11:29:00 +0100 Subject: [PATCH 088/159] Fix Python API examples so they work with Python 3 as well as Python 2. --- examples/python/all_interval_series.py | 10 +++++----- examples/python/complex/complex.py | 16 +++++++++++++--- examples/python/mus/mss.py | 7 +------ examples/python/visitor.py | 6 +++--- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/examples/python/all_interval_series.py b/examples/python/all_interval_series.py index d55017a56..216941451 100644 --- a/examples/python/all_interval_series.py +++ b/examples/python/all_interval_series.py @@ -4,7 +4,7 @@ # adjacent entries fall in the range 0,..,n-1 # This is known as the "The All-Interval Series Problem" # See http://www.csplib.org/Problems/prob007/ - +from __future__ import print_function from z3 import * import time @@ -56,7 +56,7 @@ def process_model(s, xij, n): block += [xij[i][j]] k = j values += [k] - print values + print(values) sys.stdout.flush() return block @@ -68,9 +68,9 @@ def all_models(n): block = process_model(s, xij, n) s.add(Not(And(block))) count += 1 - print s.statistics() - print time.clock() - start - print count + print(s.statistics()) + print(time.clock() - start) + print(count) set_option(verbose=1) all_models(12) diff --git a/examples/python/complex/complex.py b/examples/python/complex/complex.py index 467d76c55..3623b5f1e 100644 --- a/examples/python/complex/complex.py +++ b/examples/python/complex/complex.py @@ -6,6 +6,10 @@ # # Author: Leonardo de Moura (leonardo) ############################################ +from __future__ import print_function +import sys +if sys.version_info.major >= 3: + from functools import reduce from z3 import * def _to_complex(a): @@ -53,7 +57,7 @@ class ComplexExpr: return self if k < 0: return (self ** (-k)).inv() - return reduce(lambda x, y: x * y, [self for _ in xrange(k)], ComplexExpr(1, 0)) + return reduce(lambda x, y: x * y, [self for _ in range(k)], ComplexExpr(1, 0)) def inv(self): den = self.r*self.r + self.i*self.i @@ -63,6 +67,12 @@ class ComplexExpr: inv_other = _to_complex(other).inv() return self.__mul__(inv_other) + if sys.version_info.major >= 3: + # In python 3 the meaning of the '/' operator + # was changed. + def __truediv__(self, other): + return self.__div__(other) + def __rdiv__(self, other): other = _to_complex(other) return self.inv().__mul__(other) @@ -113,5 +123,5 @@ print(s.model()) s.add(x.i != 1) print(s.check()) # print(s.model()) -print ((3 + I) ** 2)/(5 - I) -print ((3 + I) ** -3)/(5 - I) +print(((3 + I) ** 2)/(5 - I)) +print(((3 + I) ** -3)/(5 - I)) diff --git a/examples/python/mus/mss.py b/examples/python/mus/mss.py index fd2d209da..c7b44c8a4 100644 --- a/examples/python/mus/mss.py +++ b/examples/python/mus/mss.py @@ -45,11 +45,6 @@ def enumerate_sets(solver): else: break -class CompareSetSize(): - def __call__(self, s1, s2): - return len(s1) < len(s2) - - class MSSSolver: s = Solver() varcache = {} @@ -157,7 +152,7 @@ class MSSSolver: mcs = [x for x in self.orig_soft_vars if not is_true(self.model[x])] self.s.add(Or(mcs)) core_literals = set([]) - cores.sort(CompareSetSize()) + cores.sort(key=lambda element: len(element)) for core in cores: if len(core & core_literals) == 0: self.relax_core(core) diff --git a/examples/python/visitor.py b/examples/python/visitor.py index 9255c6a80..504e2acc8 100644 --- a/examples/python/visitor.py +++ b/examples/python/visitor.py @@ -1,5 +1,5 @@ # Copyright (c) Microsoft Corporation 2015 - +from __future__ import print_function from z3 import * def visitor(e, seen): @@ -22,8 +22,8 @@ fml = x + x + y > 2 seen = {} for e in visitor(fml, seen): if is_const(e) and e.decl().kind() == Z3_OP_UNINTERPRETED: - print "Variable", e + print("Variable", e) else: - print e + print(e) From 4d6cbd3788ec2d35af9136367b80e9917e859372 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Mon, 26 Jun 2017 11:56:28 +0100 Subject: [PATCH 089/159] [CMake] Teach CMake to build the `maxsat` example as an external project. The project can be built by building the new `c_maxsat_example` target. --- examples/CMakeLists.txt | 16 +++++++++++++ examples/maxsat/CMakeLists.txt | 42 ++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 examples/maxsat/CMakeLists.txt diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3fa49f9e0..ba7f6ee59 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -23,6 +23,22 @@ ExternalProject_Add(c_example ) set_target_properties(c_example PROPERTIES EXCLUDE_FROM_ALL TRUE) +################################################################################ +# Build maxsat example project using libz3's C API as an external project +################################################################################ +ExternalProject_Add(c_maxsat_example + DEPENDS libz3 + # Configure step + SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/maxsat" + CMAKE_ARGS "-DZ3_DIR=${CMAKE_BINARY_DIR}" + # Build step + ${EXTERNAL_PROJECT_BUILD_ALWAYS_ARG} + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/c_maxsat_example_build_dir" + # Install Step + INSTALL_COMMAND "${CMAKE_COMMAND}" -E echo "" # Dummy command +) +set_target_properties(c_maxsat_example PROPERTIES EXCLUDE_FROM_ALL TRUE) + ################################################################################ # Build example project using libz3's C++ API as an external project diff --git a/examples/maxsat/CMakeLists.txt b/examples/maxsat/CMakeLists.txt new file mode 100644 index 000000000..b48e167ea --- /dev/null +++ b/examples/maxsat/CMakeLists.txt @@ -0,0 +1,42 @@ +################################################################################ +# Example maxsat project +################################################################################ +# NOTE: Even though this is a C project, libz3 uses C++. When using libz3 +# as a static library if we don't configure this project to also support +# C++ we will use the C linker rather than the C++ linker and will not link +# the C++ standard library in resulting in a link failure. +project(Z3_C_MAXSAT_EXAMPLE C CXX) +cmake_minimum_required(VERSION 2.8.12) +find_package(Z3 + REQUIRED + CONFIG + # `NO_DEFAULT_PATH` is set so that -DZ3_DIR has to be passed to find Z3. + # This should prevent us from accidently picking up an installed + # copy of Z3. This is here to benefit Z3's build sytem when building + # this project. When making your own project you probably shouldn't + # use this option. + NO_DEFAULT_PATH +) +message(STATUS "Z3_FOUND: ${Z3_FOUND}") +message(STATUS "Found Z3 ${Z3_VERSION_STRING}") +message(STATUS "Z3_DIR: ${Z3_DIR}") + +add_executable(c_maxsat_example maxsat.c) +target_include_directories(c_maxsat_example PRIVATE ${Z3_C_INCLUDE_DIRS}) +target_link_libraries(c_maxsat_example PRIVATE ${Z3_LIBRARIES}) + +if ("${CMAKE_SYSTEM_NAME}" MATCHES "[Ww]indows") + # On Windows we need to copy the Z3 libraries + # into the same directory as the executable + # so that they can be found. + foreach (z3_lib ${Z3_LIBRARIES}) + message(STATUS "Adding copy rule for ${z3_lib}") + add_custom_command(TARGET c_maxsat_example + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E copy_if_different + $ + $ + ) + endforeach() +endif() From 7db1847f51dd18f731aad7b4920d78faa9951208 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 26 Jun 2017 09:36:53 -0700 Subject: [PATCH 090/159] fix bitrot in maxsat example reference management #1116 Signed-off-by: Nikolaj Bjorner --- examples/maxsat/maxsat.c | 12 ++++++++++++ src/util/lp/sparse_matrix_instances.cpp | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/maxsat/maxsat.c b/examples/maxsat/maxsat.c index eaf01482c..45325311e 100644 --- a/examples/maxsat/maxsat.c +++ b/examples/maxsat/maxsat.c @@ -358,6 +358,7 @@ void tst_at_most_one() { Z3_context ctx = mk_context(); Z3_solver s = Z3_mk_solver(ctx); + Z3_solver_inc_ref(ctx, s); Z3_ast k1 = mk_bool_var(ctx, "k1"); Z3_ast k2 = mk_bool_var(ctx, "k2"); Z3_ast k3 = mk_bool_var(ctx, "k3"); @@ -376,7 +377,9 @@ void tst_at_most_one() if (result != Z3_L_TRUE) error("BUG"); m = Z3_solver_get_model(ctx, s); + Z3_model_inc_ref(ctx, m); printf("model:\n%s\n", Z3_model_to_string(ctx, m)); + Z3_model_dec_ref(ctx, m); Z3_solver_assert(ctx, s, mk_binary_or(ctx, k2, k3)); Z3_solver_assert(ctx, s, mk_binary_or(ctx, k1, k6)); printf("it must be sat...\n"); @@ -384,12 +387,15 @@ void tst_at_most_one() if (result != Z3_L_TRUE) error("BUG"); m = Z3_solver_get_model(ctx, s); + Z3_model_inc_ref(ctx, m); printf("model:\n%s\n", Z3_model_to_string(ctx, m)); Z3_solver_assert(ctx, s, mk_binary_or(ctx, k4, k5)); printf("it must be unsat...\n"); result = Z3_solver_check(ctx, s); if (result != Z3_L_FALSE) error("BUG"); + Z3_model_dec_ref(ctx, m); + Z3_solver_dec_ref(ctx, s); Z3_del_context(ctx); } @@ -455,7 +461,9 @@ int naive_maxsat(Z3_context ctx, Z3_solver s, unsigned num_hard_cnstrs, Z3_ast * return num_soft_cnstrs - k - 1; } m = Z3_solver_get_model(ctx, s); + Z3_model_inc_ref(ctx, m); num_disabled = get_num_disabled_soft_constraints(ctx, m, num_soft_cnstrs, aux_vars); + Z3_model_dec_ref(ctx, m); if (num_disabled > k) { error("BUG"); } @@ -506,6 +514,7 @@ int fu_malik_maxsat_step(Z3_context ctx, Z3_solver s, unsigned num_soft_cnstrs, } else { core = Z3_solver_get_unsat_core(ctx, s); + Z3_ast_vector_inc_ref(ctx, core); core_size = Z3_ast_vector_size(ctx, core); block_vars = (Z3_ast*) malloc(sizeof(Z3_ast) * core_size); k = 0; @@ -531,6 +540,7 @@ int fu_malik_maxsat_step(Z3_context ctx, Z3_solver s, unsigned num_soft_cnstrs, } } assert_at_most_one(ctx, s, k, block_vars); + Z3_ast_vector_dec_ref(ctx, core); return 0; // not done. } } @@ -598,6 +608,7 @@ int smtlib_maxsat(char * file_name, int approach) unsigned result = 0; ctx = mk_context(); s = Z3_mk_solver(ctx); + Z3_solver_inc_ref(ctx, s); Z3_parse_smtlib_file(ctx, file_name, 0, 0, 0, 0, 0, 0); hard_cnstrs = get_hard_constraints(ctx, &num_hard_cnstrs); soft_cnstrs = get_soft_constraints(ctx, &num_soft_cnstrs); @@ -615,6 +626,7 @@ int smtlib_maxsat(char * file_name, int approach) } free_cnstr_array(hard_cnstrs); free_cnstr_array(soft_cnstrs); + Z3_solver_dec_ref(ctx, s); return result; } diff --git a/src/util/lp/sparse_matrix_instances.cpp b/src/util/lp/sparse_matrix_instances.cpp index f80b60365..c06fcbf05 100644 --- a/src/util/lp/sparse_matrix_instances.cpp +++ b/src/util/lp/sparse_matrix_instances.cpp @@ -2,8 +2,8 @@ Copyright (c) 2017 Microsoft Corporation Author: Lev Nachmanson */ -#include "util/vector.h" #include +#include "util/vector.h" #include "util/lp/lp_settings.h" #include "util/lp/lu.h" #include "util/lp/sparse_matrix.hpp" From 244cbc263831823096359f4745db259f6de5845b Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 26 Jun 2017 10:04:50 -0700 Subject: [PATCH 091/159] ensure that auxiliary PB booleans are recognized during rewriting. Fixes segementation fault #1113, but does not address performance issues with quantifiers and optimization combinations Signed-off-by: Nikolaj Bjorner --- src/ast/pb_decl_plugin.h | 1 + src/ast/rewriter/pb_rewriter.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/ast/pb_decl_plugin.h b/src/ast/pb_decl_plugin.h index 0750dcac7..36b1a9512 100644 --- a/src/ast/pb_decl_plugin.h +++ b/src/ast/pb_decl_plugin.h @@ -109,6 +109,7 @@ public: bool is_ge(func_decl* a) const; bool is_ge(expr* a) const { return is_app(a) && is_ge(to_app(a)->get_decl()); } bool is_ge(expr* a, rational& k) const; + bool is_aux_bool(func_decl* f) const { return is_decl_of(f, m_fid, OP_PB_AUX_BOOL); } bool is_aux_bool(expr* e) const { return is_app_of(e, m_fid, OP_PB_AUX_BOOL); } rational get_coeff(expr* a, unsigned index) const { return get_coeff(to_app(a)->get_decl(), index); } rational get_coeff(func_decl* a, unsigned index) const; diff --git a/src/ast/rewriter/pb_rewriter.cpp b/src/ast/rewriter/pb_rewriter.cpp index 0fdbc858d..b14d350b1 100644 --- a/src/ast/rewriter/pb_rewriter.cpp +++ b/src/ast/rewriter/pb_rewriter.cpp @@ -196,6 +196,7 @@ void pb_rewriter::dump_pb_rewrite(expr* fml) { } br_status pb_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { + if (m_util.is_aux_bool(f)) return BR_FAILED; ast_manager& m = result.get_manager(); rational sum(0), maxsum(0); for (unsigned i = 0; i < num_args; ++i) { From dfe15adf7e53672c85a4f079f547b18fe9657a28 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 26 Jun 2017 16:32:44 -0700 Subject: [PATCH 092/159] fix maybe non initialized warning Signed-off-by: Lev Nachmanson --- src/util/lp/lp_primal_core_solver.h | 1 + src/util/lp/lp_primal_core_solver.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/util/lp/lp_primal_core_solver.h b/src/util/lp/lp_primal_core_solver.h index 3fada1e5d..f77aae6eb 100644 --- a/src/util/lp/lp_primal_core_solver.h +++ b/src/util/lp/lp_primal_core_solver.h @@ -460,6 +460,7 @@ public: break; default: lean_assert(false); + new_val_for_leaving = numeric_traits::zero(); // does not matter } return j; } diff --git a/src/util/lp/lp_primal_core_solver.hpp b/src/util/lp/lp_primal_core_solver.hpp index 47eec468a..969d56812 100644 --- a/src/util/lp/lp_primal_core_solver.hpp +++ b/src/util/lp/lp_primal_core_solver.hpp @@ -1139,6 +1139,7 @@ lp_primal_core_solver::get_infeasibility_cost_for_column(unsigned j) const break; default: lean_assert(false); + ret = numeric_traits::zero(); // does not matter break; } From 4d0fda81df3aad38cc62cee47758062562ed1fbe Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Tue, 27 Jun 2017 11:45:29 -0700 Subject: [PATCH 093/159] fix run of lp_solver for mps files Signed-off-by: Lev Nachmanson --- src/shell/lp_frontend.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shell/lp_frontend.cpp b/src/shell/lp_frontend.cpp index 8bed24c83..8acbd28ff 100644 --- a/src/shell/lp_frontend.cpp +++ b/src/shell/lp_frontend.cpp @@ -80,6 +80,8 @@ void run_solver(lp_params & params, char const * mps_file_name) { solver->settings().set_message_ostream(&std::cout); solver->settings().report_frequency = params.rep_freq(); solver->settings().print_statistics = params.print_stats(); + solver->settings().simplex_strategy() = lean:: simplex_strategy_enum::lu; + solver->find_maximal_solution(); *(solver->settings().get_message_ostream()) << "status is " << lp_status_to_string(solver->get_status()) << std::endl; From 1a59123819fa9da1e5ff61385a1107948c6ed1a3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 28 Jun 2017 12:49:10 +0100 Subject: [PATCH 094/159] Fixed x86/x64 issues in theory_str --- src/smt/theory_str.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/smt/theory_str.cpp b/src/smt/theory_str.cpp index 523e087f2..0671c319c 100644 --- a/src/smt/theory_str.cpp +++ b/src/smt/theory_str.cpp @@ -21,14 +21,13 @@ #include"ast_pp.h" #include"ast_ll_pp.h" #include -#include #include #include"theory_seq_empty.h" #include"theory_arith.h" #include"ast_util.h" namespace smt { - + theory_str::theory_str(ast_manager & m, theory_str_params const & params): theory(m.mk_family_id("seq")), m_params(params), @@ -99,7 +98,7 @@ namespace smt { if (defaultCharset) { // valid C strings can't contain the null byte ('\0') charSetSize = 255; - char_set.resize(256, 0); + char_set.resize(256, 0); int idx = 0; // small letters for (int i = 97; i < 123; i++) { @@ -9217,8 +9216,8 @@ namespace smt { coverAll = get_next_val_encode(val_range_map[lastestValIndi], base); } - long long l = (tries) * distance; - long long h = l; + size_t l = (tries) * distance; + size_t h = l; for (int i = 0; i < distance; i++) { if (coverAll) break; @@ -9239,10 +9238,10 @@ namespace smt { ); // ---------------------------------------------------------------------------------------- - + expr_ref_vector orList(m), andList(m); - for (long long i = l; i < h; i++) { + for (size_t i = l; i < h; i++) { orList.push_back(m.mk_eq(val_indicator, mk_string(longlong_to_string(i).c_str()) )); if (m_params.m_AggressiveValueTesting) { literal lit = mk_eq(val_indicator, mk_string(longlong_to_string(i).c_str()), false); From 1f29cebd4df633a4fea50a29b80aa756ecd0e8e7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 28 Jun 2017 14:44:41 +0000 Subject: [PATCH 095/159] Fixed backwards compatibility problem in maxsat example --- examples/maxsat/maxsat.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/examples/maxsat/maxsat.c b/examples/maxsat/maxsat.c index 45325311e..a312e79ad 100644 --- a/examples/maxsat/maxsat.c +++ b/examples/maxsat/maxsat.c @@ -348,7 +348,15 @@ void assert_at_most_k(Z3_context ctx, Z3_solver s, unsigned n, Z3_ast * lits, un */ void assert_at_most_one(Z3_context ctx, Z3_solver s, unsigned n, Z3_ast * lits) { - assert_at_most_k(ctx, s, n, lits, 1); + assert_at_most_k(ctx, s, n, lits, 1); +} + + +Z3_solver mk_solver(Z3_context ctx) +{ + Z3_solver r = Z3_mk_solver(ctx); + Z3_solver_inc_ref(ctx, r); + return r; } /** @@ -357,8 +365,7 @@ void assert_at_most_one(Z3_context ctx, Z3_solver s, unsigned n, Z3_ast * lits) void tst_at_most_one() { Z3_context ctx = mk_context(); - Z3_solver s = Z3_mk_solver(ctx); - Z3_solver_inc_ref(ctx, s); + Z3_solver s = mk_solver(ctx); Z3_ast k1 = mk_bool_var(ctx, "k1"); Z3_ast k2 = mk_bool_var(ctx, "k2"); Z3_ast k3 = mk_bool_var(ctx, "k3"); @@ -460,7 +467,7 @@ int naive_maxsat(Z3_context ctx, Z3_solver s, unsigned num_hard_cnstrs, Z3_ast * printf("unsat\n"); return num_soft_cnstrs - k - 1; } - m = Z3_solver_get_model(ctx, s); + m = Z3_solver_get_model(ctx, s); Z3_model_inc_ref(ctx, m); num_disabled = get_num_disabled_soft_constraints(ctx, m, num_soft_cnstrs, aux_vars); Z3_model_dec_ref(ctx, m); @@ -523,7 +530,7 @@ int fu_malik_maxsat_step(Z3_context ctx, Z3_solver s, unsigned num_soft_cnstrs, unsigned j; // check whether assumption[i] is in the core or not for (j = 0; j < core_size; j++) { - if (assumptions[i] == Z3_ast_vector_get(ctx, core, j)) + if (assumptions[i] == Z3_ast_vector_get(ctx, core, j)) break; } if (j < core_size) { @@ -607,8 +614,7 @@ int smtlib_maxsat(char * file_name, int approach) Z3_ast * hard_cnstrs, * soft_cnstrs; unsigned result = 0; ctx = mk_context(); - s = Z3_mk_solver(ctx); - Z3_solver_inc_ref(ctx, s); + s = mk_solver(ctx); Z3_parse_smtlib_file(ctx, file_name, 0, 0, 0, 0, 0, 0); hard_cnstrs = get_hard_constraints(ctx, &num_hard_cnstrs); soft_cnstrs = get_soft_constraints(ctx, &num_soft_cnstrs); From a28a8304b7c55e6e07dcbf92f8bd044054fce7e4 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 28 Jun 2017 13:12:12 -0700 Subject: [PATCH 096/159] Dev (#56) * introduce int_solver.h Signed-off-by: Lev Nachmanson * add int_solver class Signed-off-by: Lev Nachmanson * track which var is an integer Signed-off-by: Lev Nachmanson * add queries for integrality of vars Signed-off-by: Lev Nachmanson * resurrect lp_tst in its own director lp Signed-off-by: Lev Nachmanson * add file Signed-off-by: Lev Nachmanson * add_constraint has got a body Signed-off-by: Lev Nachmanson * fix add_constraint and substitute_terms_in_linear_expression Signed-off-by: Lev Nachmanson * after merge with Z3Prover Signed-off-by: Lev Nachmanson * adding stub check_int_feasibility() Signed-off-by: Lev Nachmanson * Dev (#50) * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * small fix in lar_solver.cpp Signed-off-by: Lev Nachmanson * adding some content to the new check_int_feasibility() Signed-off-by: Lev Nachmanson * Dev (#51) * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * adding more nlsat Signed-off-by: Nikolaj Bjorner * nlsat integration Signed-off-by: Nikolaj Bjorner * adding constraints Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * add missing initialization Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * test Signed-off-by: Lev Nachmanson * Dev (#53) * change in a comment Signed-off-by: Lev Nachmanson * Disabled debug output * removing FOCI2 interface from interp * remove foci reference from cmakelist.txt Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * adding more nlsat Signed-off-by: Nikolaj Bjorner * nlsat integration Signed-off-by: Nikolaj Bjorner * adding constraints Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * add missing initialization Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * adding nra Signed-off-by: Nikolaj Bjorner * debugging nra Signed-off-by: Nikolaj Bjorner * updates to nra_solver integration to call it directly from theory_lra instead of over lar_solver Signed-off-by: Nikolaj Bjorner * n/a Signed-off-by: Nikolaj Bjorner * integrate nlsat Signed-off-by: Nikolaj Bjorner * tidy Signed-off-by: Nikolaj Bjorner * preserve is_int flag Signed-off-by: Lev Nachmanson * remove a debug printout Signed-off-by: Lev Nachmanson * Dev (#54) * change in a comment Signed-off-by: Lev Nachmanson * Disabled debug output * removing FOCI2 interface from interp * remove foci reference from cmakelist.txt Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * adding more nlsat Signed-off-by: Nikolaj Bjorner * nlsat integration Signed-off-by: Nikolaj Bjorner * adding constraints Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * add missing initialization Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * adding nra Signed-off-by: Nikolaj Bjorner * debugging nra Signed-off-by: Nikolaj Bjorner * updates to nra_solver integration to call it directly from theory_lra instead of over lar_solver Signed-off-by: Nikolaj Bjorner * n/a Signed-off-by: Nikolaj Bjorner * integrate nlsat Signed-off-by: Nikolaj Bjorner * tidy Signed-off-by: Nikolaj Bjorner * use integer test from lra solver, updated it to work on term variables Signed-off-by: Nikolaj Bjorner * fix equality check in assume-eq Signed-off-by: Nikolaj Bjorner * fix model_is_int_feasible Signed-off-by: Lev Nachmanson * untested gcd_test() Signed-off-by: Lev Nachmanson * call fill_explanation_from_fixed_columns() Signed-off-by: Lev Nachmanson * add the call to pivot_fixed_vars_from_basis() to int_solver.cpp::check() Signed-off-by: Lev Nachmanson * port more of theory_arith_int.h Signed-off-by: Lev Nachmanson * use statistics of lar_solver by theory_lra.cpp Signed-off-by: Lev Nachmanson * port more code to int_solver.cpp Signed-off-by: Lev Nachmanson * add an assert Signed-off-by: Lev Nachmanson * more int porting Signed-off-by: Lev Nachmanson * fix a bug in pivot_fixed_vars_from_basis Signed-off-by: Lev Nachmanson * small change Signed-off-by: Lev Nachmanson * implement find_inf_int_base_column() Signed-off-by: Lev Nachmanson * catch unregistered vars in add_var_bound Signed-off-by: Lev Nachmanson * add a file Signed-off-by: Lev Nachmanson * compile for vs2012 Signed-off-by: Lev Nachmanson * fix asserts in add_var_bound Signed-off-by: Lev Nachmanson * fix the lp_solver init when workig on an mps file Signed-off-by: Lev Nachmanson * towards int_solver::check() Signed-off-by: Lev Nachmanson * change in int_solver::check() signature Signed-off-by: Lev Nachmanson * add handlers for lia moves Signed-off-by: Nikolaj Bjorner * spacing Signed-off-by: Nikolaj Bjorner --- contrib/cmake/src/test/lp/CMakeLists.txt | 6 + src/CMakeLists.txt | 2 +- src/ast/ast.cpp | 1 - src/ast/rewriter/arith_rewriter.cpp | 45 + src/ast/rewriter/arith_rewriter.h | 1 + .../simplifier/arith_simplifier_plugin.cpp | 45 + src/ast/simplifier/arith_simplifier_plugin.h | 1 + src/math/polynomial/polynomial.h | 20 +- src/nlsat/nlsat_solver.cpp | 1 + src/nlsat/nlsat_solver.h | 8 +- src/nlsat/nlsat_types.h | 8 +- src/sat/sat_types.h | 12 +- src/shell/lp_frontend.cpp | 3 +- src/smt/CMakeLists.txt | 1 + src/smt/params/smt_params_helper.pyg | 2 +- src/smt/params/theory_arith_params.h | 13 +- src/smt/smt_model_generator.cpp | 1 + src/smt/smt_setup.cpp | 5 +- src/smt/theory_lra.cpp | 413 ++-- src/test/CMakeLists.txt | 3 +- src/test/lp/CMakeLists.txt | 6 + src/test/{ => lp}/argument_parser.h | 0 src/test/{ => lp}/lp.cpp | 51 +- src/test/lp/lp_main.cpp | 14 + src/test/{ => lp}/smt_reader.h | 2 +- src/test/{ => lp}/test_file_reader.h | 0 src/util/lp/CMakeLists.txt | 7 +- src/util/lp/column_namer.h | 2 +- src/util/lp/indexed_vector.h | 9 - src/util/lp/init_lar_solver.h | 576 ----- src/util/lp/int_solver.cpp | 606 +++++ src/util/lp/int_solver.h | 100 + src/util/lp/lar_core_solver.h | 31 + src/util/lp/lar_solver.cpp | 2040 +++++++++++++++++ src/util/lp/lar_solver.h | 1611 +++---------- src/util/lp/lar_solver_instances.cpp | 13 + src/util/lp/lp_core_solver_base.h | 5 +- src/util/lp/lp_core_solver_base.hpp | 39 +- src/util/lp/lp_settings.h | 30 +- src/util/lp/lp_settings_instances.cpp | 2 +- src/util/lp/mps_reader.h | 10 +- src/util/lp/nra_solver.cpp | 264 +++ src/util/lp/nra_solver.h | 70 + src/util/lp/numeric_pair.h | 27 + src/util/lp/quick_xplain.cpp | 4 +- src/util/lp/stacked_vector.h | 5 +- src/util/lp/static_matrix_instances.cpp | 2 +- 47 files changed, 3926 insertions(+), 2191 deletions(-) create mode 100644 contrib/cmake/src/test/lp/CMakeLists.txt create mode 100644 src/test/lp/CMakeLists.txt rename src/test/{ => lp}/argument_parser.h (100%) rename src/test/{ => lp}/lp.cpp (98%) create mode 100644 src/test/lp/lp_main.cpp rename src/test/{ => lp}/smt_reader.h (99%) rename src/test/{ => lp}/test_file_reader.h (100%) delete mode 100644 src/util/lp/init_lar_solver.h create mode 100644 src/util/lp/int_solver.cpp create mode 100644 src/util/lp/int_solver.h create mode 100644 src/util/lp/lar_solver.cpp create mode 100644 src/util/lp/lar_solver_instances.cpp create mode 100644 src/util/lp/nra_solver.cpp create mode 100644 src/util/lp/nra_solver.h diff --git a/contrib/cmake/src/test/lp/CMakeLists.txt b/contrib/cmake/src/test/lp/CMakeLists.txt new file mode 100644 index 000000000..6683a1758 --- /dev/null +++ b/contrib/cmake/src/test/lp/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(lp_tst lp_main.cpp lp.cpp $ $ $ $ ) +target_compile_definitions(lp_tst PRIVATE ${Z3_COMPONENT_CXX_DEFINES}) +target_compile_options(lp_tst PRIVATE ${Z3_COMPONENT_CXX_FLAGS}) +target_include_directories(lp_tst PRIVATE ${Z3_COMPONENT_EXTRA_INCLUDE_DIRS}) +target_link_libraries(lp_tst PRIVATE ${Z3_DEPENDENT_LIBS}) +z3_append_linker_flag_list_to_target(lp_tst ${Z3_DEPENDENT_EXTRA_CXX_LINK_FLAGS}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dd440b34d..a98f92ca3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,10 +35,10 @@ endforeach() # raised if you try to declare a component is dependent on another component # that has not yet been declared. add_subdirectory(util) -add_subdirectory(util/lp) add_subdirectory(math/polynomial) add_subdirectory(sat) add_subdirectory(nlsat) +add_subdirectory(util/lp) add_subdirectory(math/hilbert) add_subdirectory(math/simplex) add_subdirectory(math/automata) diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 5f2de5170..109657675 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -1727,7 +1727,6 @@ ast * ast_manager::register_node_core(ast * n) { n->m_id = is_decl(n) ? m_decl_id_gen.mk() : m_expr_id_gen.mk(); - TRACE("ast", tout << "Object " << n->m_id << " was created.\n";); TRACE("mk_var_bug", tout << "mk_ast: " << n->m_id << "\n";); // increment reference counters diff --git a/src/ast/rewriter/arith_rewriter.cpp b/src/ast/rewriter/arith_rewriter.cpp index 2b2087e3b..fa3d69602 100644 --- a/src/ast/rewriter/arith_rewriter.cpp +++ b/src/ast/rewriter/arith_rewriter.cpp @@ -738,9 +738,54 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu result = m_util.mk_idiv0(arg1); return BR_REWRITE1; } + expr_ref quot(m()); + if (divides(arg1, arg2, quot)) { + result = m_util.mk_mul(quot, m_util.mk_idiv(arg1, arg1)); + return BR_REWRITE2; + } return BR_FAILED; } +bool arith_rewriter::divides(expr* d, expr* n, expr_ref& quot) { + if (d == n) { + quot = m_util.mk_numeral(rational(1), m_util.is_int(d)); + return true; + } + if (m_util.is_mul(n)) { + expr_ref_vector muls(m()); + muls.push_back(n); + expr* n1, *n2; + rational r1, r2; + for (unsigned i = 0; i < muls.size(); ++i) { + if (m_util.is_mul(muls[i].get(), n1, n2)) { + muls[i] = n1; + muls.push_back(n2); + --i; + } + } + if (m_util.is_numeral(d, r1) && !r1.is_zero()) { + for (unsigned i = 0; i < muls.size(); ++i) { + if (m_util.is_numeral(muls[i].get(), r2) && (r2 / r1).is_int()) { + muls[i] = m_util.mk_numeral(r2 / r1, m_util.is_int(d)); + quot = m_util.mk_mul(muls.size(), muls.c_ptr()); + return true; + } + } + } + else { + for (unsigned i = 0; i < muls.size(); ++i) { + if (d == muls[i].get()) { + muls[i] = muls.back(); + muls.pop_back(); + quot = m_util.mk_mul(muls.size(), muls.c_ptr()); + return true; + } + } + } + } + return false; +} + br_status arith_rewriter::mk_mod_core(expr * arg1, expr * arg2, expr_ref & result) { set_curr_sort(m().get_sort(arg1)); numeral v1, v2; diff --git a/src/ast/rewriter/arith_rewriter.h b/src/ast/rewriter/arith_rewriter.h index 68a60e1f0..606d73ae1 100644 --- a/src/ast/rewriter/arith_rewriter.h +++ b/src/ast/rewriter/arith_rewriter.h @@ -90,6 +90,7 @@ class arith_rewriter : public poly_rewriter { bool is_pi_integer_offset(expr * t, expr * & m); expr * mk_sin_value(rational const & k); app * mk_sqrt(rational const & k); + bool divides(expr* d, expr* n, expr_ref& quot); public: arith_rewriter(ast_manager & m, params_ref const & p = params_ref()): diff --git a/src/ast/simplifier/arith_simplifier_plugin.cpp b/src/ast/simplifier/arith_simplifier_plugin.cpp index ef320578a..52f36ab04 100644 --- a/src/ast/simplifier/arith_simplifier_plugin.cpp +++ b/src/ast/simplifier/arith_simplifier_plugin.cpp @@ -267,10 +267,55 @@ void arith_simplifier_plugin::mk_idiv(expr * arg1, expr * arg2, expr_ref & resul bool is_int; if (m_util.is_numeral(arg1, v1, is_int) && m_util.is_numeral(arg2, v2, is_int) && !v2.is_zero()) result = m_util.mk_numeral(div(v1, v2), is_int); + else if (divides(arg2, arg1, result)) { + result = m_util.mk_mul(result, m_util.mk_idiv(arg2, arg2)); + } else result = m_util.mk_idiv(arg1, arg2); } +bool arith_simplifier_plugin::divides(expr* d, expr* n, expr_ref& quot) { + ast_manager& m = m_manager; + 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; +} + + void arith_simplifier_plugin::prop_mod_const(expr * e, unsigned depth, numeral const& k, expr_ref& result) { SASSERT(m_util.is_int(e)); SASSERT(k.is_int() && k.is_pos()); diff --git a/src/ast/simplifier/arith_simplifier_plugin.h b/src/ast/simplifier/arith_simplifier_plugin.h index e6181e211..045ee0e71 100644 --- a/src/ast/simplifier/arith_simplifier_plugin.h +++ b/src/ast/simplifier/arith_simplifier_plugin.h @@ -48,6 +48,7 @@ protected: void div_monomial(expr_ref_vector& monomials, numeral const& g); void get_monomial_gcd(expr_ref_vector& monomials, numeral& g); + bool divides(expr* d, expr* n, expr_ref& quot); public: arith_simplifier_plugin(ast_manager & m, basic_simplifier_plugin & b, arith_simplifier_params & p); diff --git a/src/math/polynomial/polynomial.h b/src/math/polynomial/polynomial.h index cb1880495..b2b61f079 100644 --- a/src/math/polynomial/polynomial.h +++ b/src/math/polynomial/polynomial.h @@ -19,16 +19,16 @@ Notes: #ifndef POLYNOMIAL_H_ #define POLYNOMIAL_H_ -#include"mpz.h" -#include"rational.h" -#include"obj_ref.h" -#include"ref_vector.h" -#include"z3_exception.h" -#include"scoped_numeral.h" -#include"scoped_numeral_vector.h" -#include"params.h" -#include"mpbqi.h" -#include"rlimit.h" +#include"util/mpz.h" +#include"util/rational.h" +#include"util/obj_ref.h" +#include"util/ref_vector.h" +#include"util/z3_exception.h" +#include"util/scoped_numeral.h" +#include"util/scoped_numeral_vector.h" +#include"util/params.h" +#include"util/mpbqi.h" +#include"util/rlimit.h" class small_object_allocator; diff --git a/src/nlsat/nlsat_solver.cpp b/src/nlsat/nlsat_solver.cpp index 7582c8389..7ffb1b0a5 100644 --- a/src/nlsat/nlsat_solver.cpp +++ b/src/nlsat/nlsat_solver.cpp @@ -623,6 +623,7 @@ namespace nlsat { unsigned sz = cs.size(); for (unsigned i = 0; i < sz; i++) del_clause(cs[i]); + cs.reset(); } void del_clauses() { diff --git a/src/nlsat/nlsat_solver.h b/src/nlsat/nlsat_solver.h index 3668629cd..08902e709 100644 --- a/src/nlsat/nlsat_solver.h +++ b/src/nlsat/nlsat_solver.h @@ -21,10 +21,10 @@ Revision History: #ifndef NLSAT_SOLVER_H_ #define NLSAT_SOLVER_H_ -#include"nlsat_types.h" -#include"params.h" -#include"statistics.h" -#include"rlimit.h" +#include"nlsat/nlsat_types.h" +#include"util/params.h" +#include"util/statistics.h" +#include"util/rlimit.h" namespace nlsat { diff --git a/src/nlsat/nlsat_types.h b/src/nlsat/nlsat_types.h index 11e063a17..70da98e32 100644 --- a/src/nlsat/nlsat_types.h +++ b/src/nlsat/nlsat_types.h @@ -19,10 +19,10 @@ Revision History: #ifndef NLSAT_TYPES_H_ #define NLSAT_TYPES_H_ -#include"polynomial.h" -#include"buffer.h" -#include"sat_types.h" -#include"z3_exception.h" +#include"math/polynomial/polynomial.h" +#include"util/buffer.h" +#include"sat/sat_types.h" +#include"util/z3_exception.h" namespace algebraic_numbers { class anum; diff --git a/src/sat/sat_types.h b/src/sat/sat_types.h index 28d8d761a..97c8e0e91 100644 --- a/src/sat/sat_types.h +++ b/src/sat/sat_types.h @@ -19,12 +19,12 @@ Revision History: #ifndef SAT_TYPES_H_ #define SAT_TYPES_H_ -#include"debug.h" -#include"approx_set.h" -#include"lbool.h" -#include"z3_exception.h" -#include"common_msgs.h" -#include"vector.h" +#include"util/debug.h" +#include"util/approx_set.h" +#include"util/lbool.h" +#include"util/z3_exception.h" +#include"util/common_msgs.h" +#include"util/vector.h" #include namespace sat { diff --git a/src/shell/lp_frontend.cpp b/src/shell/lp_frontend.cpp index 8acbd28ff..213f94cb2 100644 --- a/src/shell/lp_frontend.cpp +++ b/src/shell/lp_frontend.cpp @@ -80,8 +80,7 @@ void run_solver(lp_params & params, char const * mps_file_name) { solver->settings().set_message_ostream(&std::cout); solver->settings().report_frequency = params.rep_freq(); solver->settings().print_statistics = params.print_stats(); - solver->settings().simplex_strategy() = lean:: simplex_strategy_enum::lu; - + solver->settings().simplex_strategy() = lean::simplex_strategy_enum::lu; solver->find_maximal_solution(); *(solver->settings().get_message_ostream()) << "status is " << lp_status_to_string(solver->get_status()) << std::endl; diff --git a/src/smt/CMakeLists.txt b/src/smt/CMakeLists.txt index 41890dd05..3db66eb3e 100644 --- a/src/smt/CMakeLists.txt +++ b/src/smt/CMakeLists.txt @@ -70,6 +70,7 @@ z3_add_component(smt euclid fpa grobner + nlsat lp macros normal_forms diff --git a/src/smt/params/smt_params_helper.pyg b/src/smt/params/smt_params_helper.pyg index a501f474a..6d67bfd19 100644 --- a/src/smt/params/smt_params_helper.pyg +++ b/src/smt/params/smt_params_helper.pyg @@ -36,7 +36,7 @@ def_module_params(module_name='smt', ('bv.reflect', BOOL, True, 'create enode for every bit-vector term'), ('bv.enable_int2bv', BOOL, True, 'enable support for int2bv and bv2int operators'), ('arith.random_initial_value', BOOL, False, 'use random initial values in the simplex-based procedure for linear arithmetic'), - ('arith.solver', UINT, 2, 'arithmetic solver: 0 - no solver, 1 - bellman-ford based solver (diff. logic only), 2 - simplex based solver, 3 - floyd-warshall based solver (diff. logic only) and no theory combination'), + ('arith.solver', UINT, 2, 'arithmetic solver: 0 - no solver, 1 - bellman-ford based solver (diff. logic only), 2 - simplex based solver, 3 - floyd-warshall based solver (diff. logic only) and no theory combination 4 - utvpi, 5 - infinitary lra, 6 - lra solver'), ('arith.nl', BOOL, True, '(incomplete) nonlinear arithmetic support based on Groebner basis and interval propagation'), ('arith.nl.gb', BOOL, True, 'groebner Basis computation, this option is ignored when arith.nl=false'), ('arith.nl.branching', BOOL, True, 'branching on integer variables in non linear clusters'), diff --git a/src/smt/params/theory_arith_params.h b/src/smt/params/theory_arith_params.h index 943bd711e..e71c0adad 100644 --- a/src/smt/params/theory_arith_params.h +++ b/src/smt/params/theory_arith_params.h @@ -23,12 +23,13 @@ Revision History: #include"params.h" enum arith_solver_id { - AS_NO_ARITH, - AS_DIFF_LOGIC, - AS_ARITH, - AS_DENSE_DIFF_LOGIC, - AS_UTVPI, - AS_OPTINF + AS_NO_ARITH, // 0 + AS_DIFF_LOGIC, // 1 + AS_ARITH, // 2 + AS_DENSE_DIFF_LOGIC, // 3 + AS_UTVPI, // 4 + AS_OPTINF, // 5 + AS_LRA // 6 }; enum bound_prop_mode { diff --git a/src/smt/smt_model_generator.cpp b/src/smt/smt_model_generator.cpp index b9c1ac453..c319a8d7d 100644 --- a/src/smt/smt_model_generator.cpp +++ b/src/smt/smt_model_generator.cpp @@ -388,6 +388,7 @@ namespace smt { enode * n = *it3; if (is_uninterp_const(n->get_owner()) && m_context->is_relevant(n)) { func_decl * d = n->get_owner()->get_decl(); + TRACE("mg_top_sort", tout << d->get_name() << " " << (m_hidden_ufs.contains(d)?"hidden":"visible") << "\n";); if (m_hidden_ufs.contains(d)) continue; expr * val = get_value(n); m_model->register_decl(d, val); diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index 4dd1e2510..9646bce2b 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -724,8 +724,6 @@ namespace smt { } void setup::setup_r_arith() { - // to disable theory lra - // m_context.register_plugin(alloc(smt::theory_mi_arith, m_manager, m_params)); m_context.register_plugin(alloc(smt::theory_lra, m_manager, m_params)); } @@ -789,6 +787,9 @@ namespace smt { case AS_OPTINF: m_context.register_plugin(alloc(smt::theory_inf_arith, m_manager, m_params)); break; + case AS_LRA: + setup_r_arith(); + break; default: if (m_params.m_arith_int_only && int_only) m_context.register_plugin(alloc(smt::theory_i_arith, m_manager, m_params)); diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 76e721faa..c35dbb94e 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -35,7 +35,10 @@ Revision History: #include "smt/smt_model_generator.h" #include "smt/arith_eq_adapter.h" #include "util/nat_set.h" +#include "util/lp/nra_solver.h" #include "tactic/filter_model_converter.h" +#include "math/polynomial/algebraic_numbers.h" +#include "math/polynomial/polynomial.h" namespace lp { enum bound_kind { lower_t, upper_t }; @@ -87,16 +90,12 @@ namespace lp { unsigned m_bounds_propagations; unsigned m_num_iterations; unsigned m_num_iterations_with_no_progress; - unsigned m_num_factorizations; unsigned m_need_to_solve_inf; unsigned m_fixed_eqs; unsigned m_conflicts; unsigned m_bound_propagations1; unsigned m_bound_propagations2; unsigned m_assert_diseq; - unsigned m_make_feasible; - unsigned m_max_cols; - unsigned m_max_rows; stats() { reset(); } void reset() { memset(this, 0, sizeof(*this)); @@ -118,9 +117,6 @@ namespace smt { unsigned m_bounds_lim; unsigned m_asserted_qhead; unsigned m_asserted_atoms_lim; - unsigned m_delayed_terms_lim; - unsigned m_delayed_equalities_lim; - unsigned m_delayed_defs_lim; unsigned m_underspecified_lim; unsigned m_var_trail_lim; expr* m_not_handled; @@ -144,10 +140,10 @@ namespace smt { ast_manager& m; theory_arith_params& m_arith_params; arith_util a; - arith_eq_adapter m_arith_eq_adapter; + vector m_columns; + - vector m_columns; // temporary values kept during internalization struct internalize_state { expr_ref_vector m_terms; @@ -198,14 +194,6 @@ namespace smt { }; typedef vector> var_coeffs; - struct delayed_def { - vector m_coeffs; - svector m_vars; - rational m_coeff; - theory_var m_var; - delayed_def(svector const& vars, vector const& coeffs, rational const& r, theory_var v): - m_coeffs(coeffs), m_vars(vars), m_coeff(r), m_var(v) {} - }; svector m_theory_var2var_index; // translate from theory variables to lar vars svector m_var_index2theory_var; // reverse map from lp_solver variables to theory variables @@ -224,11 +212,7 @@ namespace smt { svector m_equalities; // asserted rows corresponding to equalities. svector m_definitions; // asserted rows corresponding to definitions - bool m_delay_constraints; // configuration svector m_asserted_atoms; - app_ref_vector m_delayed_terms; - svector> m_delayed_equalities; - vector m_delayed_defs; expr* m_not_handled; ptr_vector m_underspecified; unsigned_vector m_var_trail; @@ -248,16 +232,36 @@ namespace smt { unsigned m_num_conflicts; + // non-linear arithmetic + scoped_ptr m_nra; + bool m_use_nra_model; + scoped_ptr m_a1, m_a2; + + // integer arithmetic + scoped_ptr m_lia; + struct var_value_eq { imp & m_th; var_value_eq(imp & th):m_th(th) {} - bool operator()(theory_var v1, theory_var v2) const { return m_th.get_ivalue(v1) == m_th.get_ivalue(v2) && m_th.is_int(v1) == m_th.is_int(v2); } + bool operator()(theory_var v1, theory_var v2) const { + if (m_th.is_int(v1) != m_th.is_int(v2)) { + return false; + } + return m_th.is_eq(v1, v2); + } }; struct var_value_hash { imp & m_th; var_value_hash(imp & th):m_th(th) {} - unsigned operator()(theory_var v) const { return (unsigned)std::hash()(m_th.get_ivalue(v)); } + unsigned operator()(theory_var v) const { + if (m_th.m_use_nra_model) { + return m_th.is_int(v); + } + else { + return (unsigned)std::hash()(m_th.get_ivalue(v)); + } + } }; int_hashtable m_model_eqs; @@ -289,14 +293,25 @@ namespace smt { m_solver->settings().bound_propagation() = BP_NONE != propagation_mode(); m_solver->set_propagate_bounds_on_pivoted_rows_mode(lp.bprop_on_pivoted_rows()); //m_solver->settings().set_ostream(0); + m_lia = alloc(lean::int_solver, m_solver.get()); } + void ensure_nra() { + if (!m_nra) { + m_nra = alloc(nra::solver, *m_solver.get(), m.limit(), ctx().get_params()); + for (unsigned i = 0; i < m_scopes.size(); ++i) { + m_nra->push(); + } + } + } + + void found_not_handled(expr* n) { m_not_handled = n; if (is_app(n) && is_underspecified(to_app(n))) { + TRACE("arith", tout << "Unhandled: " << mk_pp(n, m) << "\n";); m_underspecified.push_back(to_app(n)); } - TRACE("arith", tout << "Unhandled: " << mk_pp(n, m) << "\n";); } bool is_numeral(expr* term, rational& r) { @@ -366,6 +381,14 @@ namespace smt { terms[index] = n1; st.terms_to_internalize().push_back(n2); } + else if (a.is_mul(n)) { + theory_var v; + internalize_mul(to_app(n), v, r); + coeffs[index] *= r; + coeffs[vars.size()] = coeffs[index]; + vars.push_back(v); + ++index; + } else if (a.is_numeral(n, r)) { coeff += coeffs[index]*r; ++index; @@ -415,6 +438,44 @@ namespace smt { } } + void internalize_mul(app* t, theory_var& v, rational& r) { + SASSERT(a.is_mul(t)); + bool _has_var = has_var(t); + if (!_has_var) { + internalize_args(t); + mk_enode(t); + } + r = rational::one(); + rational r1; + v = mk_var(t); + svector vars; + ptr_vector todo; + todo.push_back(t); + while (!todo.empty()) { + expr* n = todo.back(); + todo.pop_back(); + expr* n1, *n2; + if (a.is_mul(n, n1, n2)) { + todo.push_back(n1); + todo.push_back(n2); + } + else if (a.is_numeral(n, r1)) { + r *= r1; + } + else { + if (!ctx().e_internalized(n)) { + ctx().internalize(n, false); + } + vars.push_back(get_var_index(mk_var(n))); + } + } + TRACE("arith", tout << mk_pp(t, m) << "\n";); + if (!_has_var) { + ensure_nra(); + m_nra->add_monomial(get_var_index(v), vars.size(), vars.c_ptr()); + } + } + enode * mk_enode(app * n) { if (ctx().e_internalized(n)) { return get_enode(n); @@ -459,6 +520,14 @@ namespace smt { return m_arith_params.m_arith_reflect || is_underspecified(n); } + bool has_var(expr* n) { + if (!ctx().e_internalized(n)) { + return false; + } + enode* e = get_enode(n); + return th.is_attached_to_var(e); + } + theory_var mk_var(expr* n, bool internalize = true) { if (!ctx().e_internalized(n)) { ctx().internalize(n, false); @@ -487,7 +556,7 @@ namespace smt { result = m_theory_var2var_index[v]; } if (result == UINT_MAX) { - result = m_solver->add_var(v); // TBD: is_int(v); + result = m_solver->add_var(v, is_int(v)); m_theory_var2var_index.setx(v, result, UINT_MAX); m_var_index2theory_var.setx(result, v, UINT_MAX); m_var_trail.push_back(v); @@ -549,14 +618,6 @@ namespace smt { m_definitions.setx(index, v, null_theory_var); ++m_stats.m_add_rows; } - - void internalize_eq(delayed_def const& d) { - scoped_internalize_state st(*this); - st.vars().append(d.m_vars); - st.coeffs().append(d.m_coeffs); - init_left_side(st); - add_def_constraint(m_solver->add_constraint(m_left_side, lean::EQ, -d.m_coeff), d.m_var); - } void internalize_eq(theory_var v1, theory_var v2) { enode* n1 = get_enode(v1); @@ -650,15 +711,14 @@ namespace smt { a(m), m_arith_eq_adapter(th, ap, a), m_internalize_head(0), - m_delay_constraints(false), - m_delayed_terms(m), m_not_handled(0), m_asserted_qhead(0), m_assume_eq_head(0), m_num_conflicts(0), m_model_eqs(DEFAULT_HASHTABLE_INITIAL_CAPACITY, var_value_hash(*this), var_value_eq(*this)), m_solver(0), - m_resource_limit(*this) { + m_resource_limit(*this), + m_use_nra_model(false) { } ~imp() { @@ -671,12 +731,8 @@ namespace smt { } bool internalize_atom(app * atom, bool gate_ctx) { - if (m_delay_constraints) { - return internalize_atom_lazy(atom, gate_ctx); - } - else { - return internalize_atom_strict(atom, gate_ctx); - } + return internalize_atom_strict(atom, gate_ctx); + } bool internalize_atom_strict(app * atom, bool gate_ctx) { @@ -710,54 +766,11 @@ namespace smt { //add_use_lists(b); return true; } - - bool internalize_atom_lazy(app * atom, bool gate_ctx) { - SASSERT(!ctx().b_internalized(atom)); - bool_var bv = ctx().mk_bool_var(atom); - ctx().set_var_theory(bv, get_id()); - expr* n1, *n2; - rational r; - lp::bound_kind k; - theory_var v = null_theory_var; - scoped_internalize_state st(*this); - if (a.is_le(atom, n1, n2) && is_numeral(n2, r) && is_app(n1)) { - v = internalize_def(to_app(n1), st); - k = lp::upper_t; - } - else if (a.is_ge(atom, n1, n2) && is_numeral(n2, r) && is_app(n1)) { - v = internalize_def(to_app(n1), st); - k = lp::lower_t; - } - else { - TRACE("arith", tout << "Could not internalize " << mk_pp(atom, m) << "\n";); - found_not_handled(atom); - return true; - } - lp::bound* b = alloc(lp::bound, bv, v, r, k); - m_bounds[v].push_back(b); - updt_unassigned_bounds(v, +1); - m_bounds_trail.push_back(v); - m_bool_var2bound.insert(bv, b); - TRACE("arith", tout << "Internalized " << mk_pp(atom, m) << "\n";); - if (!is_unit_var(st) && m_bounds[v].size() == 1) { - m_delayed_defs.push_back(delayed_def(st.vars(), st.coeffs(), st.coeff(), v)); - } - return true; - } bool internalize_term(app * term) { if (ctx().e_internalized(term) && th.is_attached_to_var(ctx().get_enode(term))) { // skip } - else if (m_delay_constraints) { - scoped_internalize_state st(*this); - linearize_term(term, st); // ensure that a theory_var was created. - SASSERT(ctx().e_internalized(term)); - if(!th.is_attached_to_var(ctx().get_enode(term))) { - mk_var(term); - } - m_delayed_terms.push_back(term); - } else { internalize_def(term); } @@ -783,13 +796,8 @@ namespace smt { } void new_eq_eh(theory_var v1, theory_var v2) { - if (m_delay_constraints) { - m_delayed_equalities.push_back(std::make_pair(v1, v2)); - } - else { - // or internalize_eq(v1, v2); - m_arith_eq_adapter.new_eq_eh(v1, v2); - } + // or internalize_eq(v1, v2); + m_arith_eq_adapter.new_eq_eh(v1, v2); } bool use_diseqs() const { @@ -808,13 +816,11 @@ namespace smt { s.m_bounds_lim = m_bounds_trail.size(); s.m_asserted_qhead = m_asserted_qhead; s.m_asserted_atoms_lim = m_asserted_atoms.size(); - s.m_delayed_terms_lim = m_delayed_terms.size(); - s.m_delayed_equalities_lim = m_delayed_equalities.size(); - s.m_delayed_defs_lim = m_delayed_defs.size(); s.m_not_handled = m_not_handled; s.m_underspecified_lim = m_underspecified.size(); s.m_var_trail_lim = m_var_trail.size(); - if (!m_delay_constraints) m_solver->push(); + m_solver->push(); + if (m_nra) m_nra->push(); } void pop_scope_eh(unsigned num_scopes) { @@ -835,18 +841,16 @@ namespace smt { m_theory_var2var_index[m_var_trail[i]] = UINT_MAX; } m_asserted_atoms.shrink(m_scopes[old_size].m_asserted_atoms_lim); - m_delayed_terms.shrink(m_scopes[old_size].m_delayed_terms_lim); - m_delayed_defs.shrink(m_scopes[old_size].m_delayed_defs_lim); - m_delayed_equalities.shrink(m_scopes[old_size].m_delayed_equalities_lim); m_asserted_qhead = m_scopes[old_size].m_asserted_qhead; m_underspecified.shrink(m_scopes[old_size].m_underspecified_lim); m_var_trail.shrink(m_scopes[old_size].m_var_trail_lim); m_not_handled = m_scopes[old_size].m_not_handled; m_scopes.resize(old_size); - if (!m_delay_constraints) m_solver->pop(num_scopes); + m_solver->pop(num_scopes); // VERIFY(l_false != make_feasible()); m_new_bounds.reset(); m_to_check.reset(); + if (m_nra) m_nra->pop(num_scopes); TRACE("arith", tout << "num scopes: " << num_scopes << " new scope level: " << m_scopes.size() << "\n";); } @@ -1080,7 +1084,9 @@ namespace smt { } tout << "\n"; ); - m_solver->random_update(vars.size(), vars.c_ptr()); + if (!m_use_nra_model) { + m_solver->random_update(vars.size(), vars.c_ptr()); + } m_model_eqs.reset(); TRACE("arith", display(tout);); @@ -1130,54 +1136,69 @@ namespace smt { enode* n2 = get_enode(v2); m_assume_eq_head++; CTRACE("arith", - get_ivalue(v1) == get_ivalue(v2) && n1->get_root() != n2->get_root(), + is_eq(v1, v2) && n1->get_root() != n2->get_root(), tout << "assuming eq: v" << v1 << " = v" << v2 << "\n";); - if (get_ivalue(v1) == get_ivalue(v2) && n1->get_root() != n2->get_root() && th.assume_eq(n1, n2)) { + if (is_eq(v1, v2) && n1->get_root() != n2->get_root() && th.assume_eq(n1, n2)) { return true; } } return false; } + bool is_eq(theory_var v1, theory_var v2) { + if (m_use_nra_model) { + return m_nra->am().eq(nl_value(v1, *m_a1), nl_value(v2, *m_a2)); + } + else { + return get_ivalue(v1) == get_ivalue(v2); + } + } + bool has_delayed_constraints() const { - return !(m_asserted_atoms.empty() && m_delayed_terms.empty() && m_delayed_equalities.empty()); + return !m_asserted_atoms.empty(); } final_check_status final_check_eh() { + m_use_nra_model = false; lbool is_sat = l_true; - if (m_delay_constraints) { - init_solver(); - for (unsigned i = 0; i < m_asserted_atoms.size(); ++i) { - bool_var bv = m_asserted_atoms[i].m_bv; - assert_bound(bv, m_asserted_atoms[i].m_is_true, *m_bool_var2bound.find(bv)); - } - for (unsigned i = 0; i < m_delayed_terms.size(); ++i) { - internalize_def(m_delayed_terms[i].get()); - } - for (unsigned i = 0; i < m_delayed_defs.size(); ++i) { - internalize_eq(m_delayed_defs[i]); - } - for (unsigned i = 0; i < m_delayed_equalities.size(); ++i) { - std::pair const& eq = m_delayed_equalities[i]; - internalize_eq(eq.first, eq.second); - } - is_sat = make_feasible(); - } - else if (m_solver->get_status() != lean::lp_status::OPTIMAL) { + if (m_solver->get_status() != lean::lp_status::OPTIMAL) { is_sat = make_feasible(); } + final_check_status st = FC_DONE; switch (is_sat) { case l_true: + if (delayed_assume_eqs()) { return FC_CONTINUE; } if (assume_eqs()) { return FC_CONTINUE; } - if (m_not_handled != 0) { - return FC_GIVEUP; + + switch (check_lia()) { + case l_true: + break; + case l_false: + return FC_CONTINUE; + case l_undef: + st = FC_GIVEUP; + break; } - return FC_DONE; + + switch (check_nra()) { + case l_true: + break; + case l_false: + return FC_CONTINUE; + case l_undef: + st = FC_GIVEUP; + break; + } + if (m_not_handled != 0) { + st = FC_GIVEUP; + } + + return st; case l_false: set_conflict(); return FC_CONTINUE; @@ -1190,6 +1211,70 @@ namespace smt { return FC_GIVEUP; } + // create a bound atom representing term >= k + lp::bound* mk_bound(lean::lar_term const& term, rational const& k) { + NOT_IMPLEMENTED_YET(); + lp::bound_kind bkind = lp::bound_kind::lower_t; + bool_var bv = null_bool_var; + theory_var v = null_theory_var; + lp::bound* result = alloc(lp::bound, bv, v, k, bkind); + return result; + } + + lbool check_lia() { + std::cout << "called check_lia()\n"; + lean::lar_term term; + lean::mpq k; + lean::explanation ex; // TBD, this should be streamlined accross different explanations + switch(m_lia->check(term, k, ex)) { + case lean::lia_move::ok: + return l_true; + case lean::lia_move::branch: + // branch on term <= k + NOT_IMPLEMENTED_YET(); + return l_false; + case lean::lia_move::cut: + // m_explanation implies term <= k + m_explanation = ex.m_explanation; + NOT_IMPLEMENTED_YET(); + return l_false; + case lean::lia_move::conflict: + // ex contains unsat core + m_explanation = ex.m_explanation; + set_conflict1(); + return l_false; + case lean::lia_move::give_up: + return l_undef; + default: + UNREACHABLE(); + } + return l_undef; + } + + lbool check_nra() { + m_use_nra_model = false; + if (m.canceled()) return l_undef; + if (!m_nra) return l_true; + if (!m_nra->need_check()) return l_true; + m_a1 = 0; m_a2 = 0; + lbool r = m_nra->check(m_explanation); + m_a1 = alloc(scoped_anum, m_nra->am()); + m_a2 = alloc(scoped_anum, m_nra->am()); + switch (r) { + case l_false: + set_conflict1(); + break; + case l_true: + m_use_nra_model = true; + if (assume_eqs()) { + return l_false; + } + break; + default: + break; + } + return r; + } /** \brief We must redefine this method, because theory of arithmetic contains @@ -1259,14 +1344,13 @@ namespace smt { #else propagate_bound(bv, is_true, b); #endif - if (!m_delay_constraints) { - lp::bound& b = *m_bool_var2bound.find(bv); - assert_bound(bv, is_true, b); - } + lp::bound& b = *m_bool_var2bound.find(bv); + assert_bound(bv, is_true, b); + ++m_asserted_qhead; } - if (m_delay_constraints || ctx().inconsistent()) { + if (ctx().inconsistent()) { m_to_check.reset(); return; } @@ -2133,18 +2217,8 @@ namespace smt { } lbool make_feasible() { - reset_variable_values(); - ++m_stats.m_make_feasible; - if (m_solver->A_r().column_count() > m_stats.m_max_cols) - m_stats.m_max_cols = m_solver->A_r().column_count(); - if (m_solver->A_r().row_count() > m_stats.m_max_rows) - m_stats.m_max_rows = m_solver->A_r().row_count(); + auto status = m_solver->find_feasible_solution(); TRACE("arith_verbose", display(tout);); - lean::lp_status status = m_solver->find_feasible_solution(); - m_stats.m_num_iterations = m_solver->settings().st().m_total_iterations; - m_stats.m_num_factorizations = m_solver->settings().st().m_num_factorizations; - m_stats.m_need_to_solve_inf = m_solver->settings().st().m_need_to_solve_inf; - switch (status) { case lean::lp_status::INFEASIBLE: return l_false; @@ -2197,11 +2271,15 @@ namespace smt { } void set_conflict() { + m_explanation.clear(); + m_solver->get_infeasibility_explanation(m_explanation); + set_conflict1(); + } + + void set_conflict1() { m_eqs.reset(); m_core.reset(); m_params.reset(); - m_explanation.clear(); - m_solver->get_infeasibility_explanation(m_explanation); // m_solver->shrink_explanation_to_minimum(m_explanation); // todo, enable when perf is fixed /* static unsigned cn = 0; @@ -2250,9 +2328,43 @@ namespace smt { TRACE("arith", display(tout);); } + nlsat::anum const& nl_value(theory_var v, scoped_anum& r) { + SASSERT(m_nra); + SASSERT(m_use_nra_model); + lean::var_index vi = m_theory_var2var_index[v]; + if (m_solver->is_term(vi)) { + lean::lar_term const& term = m_solver->get_term(vi); + scoped_anum r1(m_nra->am()); + m_nra->am().set(r, term.m_v.to_mpq()); + + for (auto const coeff : term.m_coeffs) { + lean::var_index wi = coeff.first; + m_nra->am().set(r1, coeff.second.to_mpq()); + m_nra->am().mul(m_nra->value(wi), r1, r1); + m_nra->am().add(r1, r, r); + } + return r; + } + else { + return m_nra->value(vi); + } + } + model_value_proc * mk_value(enode * n, model_generator & mg) { theory_var v = n->get_th_var(get_id()); - return alloc(expr_wrapper_proc, m_factory->mk_value(get_value(v), m.get_sort(n->get_owner()))); + expr* o = n->get_owner(); + if (m_use_nra_model) { + anum const& an = nl_value(v, *m_a1); + if (a.is_int(o) && !m_nra->am().is_int(an)) { + return alloc(expr_wrapper_proc, a.mk_numeral(rational::zero(), a.is_int(o))); + } + return alloc(expr_wrapper_proc, a.mk_numeral(nl_value(v, *m_a1), a.is_int(o))); + } + else { + rational r = get_value(v); + if (a.is_int(o) && !r.is_int()) r = floor(r); + return alloc(expr_wrapper_proc, m_factory->mk_value(r, m.get_sort(o))); + } } bool get_value(enode* n, expr_ref& r) { @@ -2278,6 +2390,7 @@ namespace smt { if (dump_lemmas()) { ctx().display_lemma_as_smt_problem(m_core.size(), m_core.c_ptr(), m_eqs.size(), m_eqs.c_ptr(), false_literal); } + if (m_arith_params.m_arith_mode == AS_LRA) return true; context nctx(m, ctx().get_fparams(), ctx().get_params()); add_background(nctx); bool result = l_true != nctx.check(); @@ -2290,6 +2403,7 @@ namespace smt { if (dump_lemmas()) { ctx().display_lemma_as_smt_problem(m_core.size(), m_core.c_ptr(), m_eqs.size(), m_eqs.c_ptr(), lit); } + if (m_arith_params.m_arith_mode == AS_LRA) return true; context nctx(m, ctx().get_fparams(), ctx().get_params()); m_core.push_back(~lit); add_background(nctx); @@ -2301,6 +2415,7 @@ namespace smt { } bool validate_eq(enode* x, enode* y) { + if (m_arith_params.m_arith_mode == AS_LRA) return true; context nctx(m, ctx().get_fparams(), ctx().get_params()); add_background(nctx); nctx.assert_expr(m.mk_not(m.mk_eq(x->get_owner(), y->get_owner()))); @@ -2496,7 +2611,7 @@ namespace smt { st.update("arith-rows", m_stats.m_add_rows); st.update("arith-propagations", m_stats.m_bounds_propagations); st.update("arith-iterations", m_stats.m_num_iterations); - st.update("arith-factorizations", m_stats.m_num_factorizations); + st.update("arith-factorizations", m_solver->settings().st().m_num_factorizations); st.update("arith-pivots", m_stats.m_need_to_solve_inf); st.update("arith-plateau-iterations", m_stats.m_num_iterations_with_no_progress); st.update("arith-fixed-eqs", m_stats.m_fixed_eqs); @@ -2504,9 +2619,9 @@ namespace smt { st.update("arith-bound-propagations-lp", m_stats.m_bound_propagations1); st.update("arith-bound-propagations-cheap", m_stats.m_bound_propagations2); st.update("arith-diseq", m_stats.m_assert_diseq); - st.update("arith-make-feasible", m_stats.m_make_feasible); - st.update("arith-max-columns", m_stats.m_max_cols); - st.update("arith-max-rows", m_stats.m_max_rows); + st.update("arith-make-feasible", m_solver->settings().st().m_make_feasible); + st.update("arith-max-columns", m_solver->settings().st().m_max_cols); + st.update("arith-max-rows", m_solver->settings().st().m_max_rows); } }; diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index b395c09e6..f92525069 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(fuzzing) +add_subdirectory(lp) ################################################################################ # z3-test executable ################################################################################ @@ -117,7 +118,7 @@ add_executable(test-z3 upolynomial.cpp var_subst.cpp vector.cpp - lp.cpp + lp/lp.cpp ${z3_test_extra_object_files} ) z3_add_install_tactic_rule(${z3_test_deps}) diff --git a/src/test/lp/CMakeLists.txt b/src/test/lp/CMakeLists.txt new file mode 100644 index 000000000..6683a1758 --- /dev/null +++ b/src/test/lp/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(lp_tst lp_main.cpp lp.cpp $ $ $ $ ) +target_compile_definitions(lp_tst PRIVATE ${Z3_COMPONENT_CXX_DEFINES}) +target_compile_options(lp_tst PRIVATE ${Z3_COMPONENT_CXX_FLAGS}) +target_include_directories(lp_tst PRIVATE ${Z3_COMPONENT_EXTRA_INCLUDE_DIRS}) +target_link_libraries(lp_tst PRIVATE ${Z3_DEPENDENT_LIBS}) +z3_append_linker_flag_list_to_target(lp_tst ${Z3_DEPENDENT_EXTRA_CXX_LINK_FLAGS}) diff --git a/src/test/argument_parser.h b/src/test/lp/argument_parser.h similarity index 100% rename from src/test/argument_parser.h rename to src/test/lp/argument_parser.h diff --git a/src/test/lp.cpp b/src/test/lp/lp.cpp similarity index 98% rename from src/test/lp.cpp rename to src/test/lp/lp.cpp index 9e05112f5..71032d013 100644 --- a/src/test/lp.cpp +++ b/src/test/lp/lp.cpp @@ -2695,8 +2695,8 @@ void test_term() { lar_solver solver; unsigned _x = 0; unsigned _y = 1; - var_index x = solver.add_var(_x); - var_index y = solver.add_var(_y); + var_index x = solver.add_var(_x, false); + var_index y = solver.add_var(_y, false); vector> term_ls; term_ls.push_back(std::pair((int)1, x)); @@ -2709,9 +2709,16 @@ void test_term() { ls.push_back(std::pair((int)1, z)); solver.add_constraint(ls, lconstraint_kind::EQ, mpq(0)); + ls.clear(); + ls.push_back(std::pair((int)1, x)); + solver.add_constraint(ls, lconstraint_kind::LT, mpq(0)); + ls.push_back(std::pair((int)2, y)); + solver.add_constraint(ls, lconstraint_kind::GT, mpq(0)); auto status = solver.solve(); std::cout << lp_status_to_string(status) << std::endl; std::unordered_map model; + if (status != OPTIMAL) + return; solver.get_model(model); for (auto & t : model) { @@ -2723,8 +2730,8 @@ void test_term() { void test_evidence_for_total_inf_simple(argument_parser & args_parser) { lar_solver solver; - var_index x = solver.add_var(0); - var_index y = solver.add_var(1); + var_index x = solver.add_var(0, false); + var_index y = solver.add_var(1, false); solver.add_var_bound(x, LE, -mpq(1)); solver.add_var_bound(y, GE, mpq(0)); vector> ls; @@ -2758,9 +2765,9 @@ If b becomes basic variable, then it is likely the old solver ends up with a row return true; }; lar_solver ls; - unsigned a = ls.add_var(0); - unsigned b = ls.add_var(1); - unsigned c = ls.add_var(2); + unsigned a = ls.add_var(0, false); + unsigned b = ls.add_var(1, false); + unsigned c = ls.add_var(2, false); vector> coeffs; coeffs.push_back(std::pair(1, a)); coeffs.push_back(std::pair(-1, c)); @@ -2823,8 +2830,8 @@ If x9 becomes basic variable, then it is likely the old solver ends up with a ro } void test_bound_propagation_one_row() { lar_solver ls; - unsigned x0 = ls.add_var(0); - unsigned x1 = ls.add_var(1); + unsigned x0 = ls.add_var(0, false); + unsigned x1 = ls.add_var(1, false); vector> c; c.push_back(std::pair(1, x0)); c.push_back(std::pair(-1, x1)); @@ -2837,8 +2844,8 @@ void test_bound_propagation_one_row() { } void test_bound_propagation_one_row_with_bounded_vars() { lar_solver ls; - unsigned x0 = ls.add_var(0); - unsigned x1 = ls.add_var(1); + unsigned x0 = ls.add_var(0, false); + unsigned x1 = ls.add_var(1, false); vector> c; c.push_back(std::pair(1, x0)); c.push_back(std::pair(-1, x1)); @@ -2853,8 +2860,8 @@ void test_bound_propagation_one_row_with_bounded_vars() { } void test_bound_propagation_one_row_mixed() { lar_solver ls; - unsigned x0 = ls.add_var(0); - unsigned x1 = ls.add_var(1); + unsigned x0 = ls.add_var(0, false); + unsigned x1 = ls.add_var(1, false); vector> c; c.push_back(std::pair(1, x0)); c.push_back(std::pair(-1, x1)); @@ -2868,9 +2875,9 @@ void test_bound_propagation_one_row_mixed() { void test_bound_propagation_two_rows() { lar_solver ls; - unsigned x = ls.add_var(0); - unsigned y = ls.add_var(1); - unsigned z = ls.add_var(2); + unsigned x = ls.add_var(0, false); + unsigned y = ls.add_var(1, false); + unsigned z = ls.add_var(2, false); vector> c; c.push_back(std::pair(1, x)); c.push_back(std::pair(2, y)); @@ -2892,9 +2899,9 @@ void test_bound_propagation_two_rows() { void test_total_case_u() { std::cout << "test_total_case_u\n"; lar_solver ls; - unsigned x = ls.add_var(0); - unsigned y = ls.add_var(1); - unsigned z = ls.add_var(2); + unsigned x = ls.add_var(0, false); + unsigned y = ls.add_var(1, false); + unsigned z = ls.add_var(2, false); vector> c; c.push_back(std::pair(1, x)); c.push_back(std::pair(2, y)); @@ -2918,9 +2925,9 @@ bool contains_j_kind(unsigned j, lconstraint_kind kind, const mpq & rs, const ve void test_total_case_l(){ std::cout << "test_total_case_l\n"; lar_solver ls; - unsigned x = ls.add_var(0); - unsigned y = ls.add_var(1); - unsigned z = ls.add_var(2); + unsigned x = ls.add_var(0, false); + unsigned y = ls.add_var(1, false); + unsigned z = ls.add_var(2, false); vector> c; c.push_back(std::pair(1, x)); c.push_back(std::pair(2, y)); diff --git a/src/test/lp/lp_main.cpp b/src/test/lp/lp_main.cpp new file mode 100644 index 000000000..a301f38c6 --- /dev/null +++ b/src/test/lp/lp_main.cpp @@ -0,0 +1,14 @@ +void gparams_register_modules(){} +void mem_initialize() {} +void mem_finalize() {} +#include "util/rational.h" +namespace lean { +void test_lp_local(int argc, char**argv); +} +int main(int argn, char**argv){ + rational::initialize(); + lean::test_lp_local(argn, argv); + rational::finalize(); + return 0; +} + diff --git a/src/test/smt_reader.h b/src/test/lp/smt_reader.h similarity index 99% rename from src/test/smt_reader.h rename to src/test/lp/smt_reader.h index 38e3f4157..dd38c6bcd 100644 --- a/src/test/smt_reader.h +++ b/src/test/lp/smt_reader.h @@ -376,7 +376,7 @@ namespace lean { void add_constraint_to_solver(lar_solver * solver, formula_constraint & fc) { vector> ls; for (auto & it : fc.m_coeffs) { - ls.push_back(std::make_pair(it.first, solver->add_var(register_name(it.second)))); + ls.push_back(std::make_pair(it.first, solver->add_var(register_name(it.second), false))); } solver->add_constraint(ls, fc.m_kind, fc.m_right_side); } diff --git a/src/test/test_file_reader.h b/src/test/lp/test_file_reader.h similarity index 100% rename from src/test/test_file_reader.h rename to src/test/lp/test_file_reader.h diff --git a/src/util/lp/CMakeLists.txt b/src/util/lp/CMakeLists.txt index 57ebecc8d..72c2482bb 100644 --- a/src/util/lp/CMakeLists.txt +++ b/src/util/lp/CMakeLists.txt @@ -8,6 +8,8 @@ z3_add_component(lp dense_matrix_instances.cpp eta_matrix_instances.cpp indexed_vector_instances.cpp + int_solver.cpp + lar_solver_instances.cpp lar_core_solver_instances.cpp lp_core_solver_base_instances.cpp lp_dual_core_solver_instances.cpp @@ -18,8 +20,9 @@ z3_add_component(lp lp_solver_instances.cpp lu_instances.cpp matrix_instances.cpp + nra_solver.cpp permutation_matrix_instances.cpp - quick_xplain.cpp + quick_xplain.cpp row_eta_matrix_instances.cpp scaler_instances.cpp sparse_matrix_instances.cpp @@ -28,6 +31,8 @@ z3_add_component(lp random_updater_instances.cpp COMPONENT_DEPENDENCIES util + polynomial + nlsat PYG_FILES lp_params.pyg ) diff --git a/src/util/lp/column_namer.h b/src/util/lp/column_namer.h index 1a10a5a23..a3fe05dd0 100644 --- a/src/util/lp/column_namer.h +++ b/src/util/lp/column_namer.h @@ -15,7 +15,7 @@ public: T a; unsigned i; while (it->next(a, i)) { - coeff.emplace_back(a, i); + coeff.push_back(std::make_pair(a, i)); } print_linear_combination_of_column_indices(coeff, out); } diff --git a/src/util/lp/indexed_vector.h b/src/util/lp/indexed_vector.h index 6e6a6009b..4b9a7767d 100644 --- a/src/util/lp/indexed_vector.h +++ b/src/util/lp/indexed_vector.h @@ -75,16 +75,7 @@ public: } void set_value(const T& value, unsigned index); - void set_value_as_in_dictionary(unsigned index) { - lean_assert(index < m_data.size()); - T & loc = m_data[index]; - if (is_zero(loc)) { - m_index.push_back(index); - loc = one_of_type(); // use as a characteristic function - } - } - void clear(); void clear_all(); const T& operator[] (unsigned i) const { diff --git a/src/util/lp/init_lar_solver.h b/src/util/lp/init_lar_solver.h deleted file mode 100644 index 3fc29f25b..000000000 --- a/src/util/lp/init_lar_solver.h +++ /dev/null @@ -1,576 +0,0 @@ -/* - Copyright (c) 2017 Microsoft Corporation - Author: Lev Nachmanson -*/ - -// here we are inside lean::lar_solver class - -bool strategy_is_undecided() const { - return m_settings.simplex_strategy() == simplex_strategy_enum::undecided; -} - -var_index add_var(unsigned ext_j) { - var_index i; - lean_assert (ext_j < m_terms_start_index); - - if (ext_j >= m_terms_start_index) - throw 0; // todo : what is the right way to exit? - - if (try_get_val(m_ext_vars_to_columns, ext_j, i)) { - return i; - } - lean_assert(m_vars_to_ul_pairs.size() == A_r().column_count()); - i = A_r().column_count(); - m_vars_to_ul_pairs.push_back (ul_pair(static_cast(-1))); - add_non_basic_var_to_core_fields(ext_j); - lean_assert(sizes_are_correct()); - return i; -} - -void register_new_ext_var_index(unsigned ext_v) { - lean_assert(!contains(m_ext_vars_to_columns, ext_v)); - unsigned j = static_cast(m_ext_vars_to_columns.size()); - m_ext_vars_to_columns[ext_v] = j; - lean_assert(m_columns_to_ext_vars_or_term_indices.size() == j); - m_columns_to_ext_vars_or_term_indices.push_back(ext_v); -} - -void add_non_basic_var_to_core_fields(unsigned ext_j) { - register_new_ext_var_index(ext_j); - m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column); - m_columns_with_changed_bound.increase_size_by_one(); - add_new_var_to_core_fields_for_mpq(false); - if (use_lu()) - add_new_var_to_core_fields_for_doubles(false); -} - -void add_new_var_to_core_fields_for_doubles(bool register_in_basis) { - unsigned j = A_d().column_count(); - A_d().add_column(); - lean_assert(m_mpq_lar_core_solver.m_d_x.size() == j); - // lean_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 - 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_upper_bounds.resize(j + 1); - lean_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) { - A_d().add_row(); - m_mpq_lar_core_solver.m_d_heading.push_back(m_mpq_lar_core_solver.m_d_basis.size()); - m_mpq_lar_core_solver.m_d_basis.push_back(j); - }else { - m_mpq_lar_core_solver.m_d_heading.push_back(- static_cast(m_mpq_lar_core_solver.m_d_nbasis.size()) - 1); - m_mpq_lar_core_solver.m_d_nbasis.push_back(j); - } -} - -void add_new_var_to_core_fields_for_mpq(bool register_in_basis) { - unsigned j = A_r().column_count(); - A_r().add_column(); - lean_assert(m_mpq_lar_core_solver.m_r_x.size() == j); - // lean_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 - 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_upper_bounds.increase_size_by_one(); - m_mpq_lar_core_solver.m_r_solver.m_inf_set.increase_size_by_one(); - m_mpq_lar_core_solver.m_r_solver.m_costs.resize(j + 1); - m_mpq_lar_core_solver.m_r_solver.m_d.resize(j + 1); - lean_assert(m_mpq_lar_core_solver.m_r_heading.size() == j); // as A().column_count() on the entry to the method - if (register_in_basis) { - A_r().add_row(); - m_mpq_lar_core_solver.m_r_heading.push_back(m_mpq_lar_core_solver.m_r_basis.size()); - m_mpq_lar_core_solver.m_r_basis.push_back(j); - if (m_settings.bound_propagation()) - m_rows_with_changed_bounds.insert(A_r().row_count() - 1); - } else { - m_mpq_lar_core_solver.m_r_heading.push_back(- static_cast(m_mpq_lar_core_solver.m_r_nbasis.size()) - 1); - m_mpq_lar_core_solver.m_r_nbasis.push_back(j); - } -} - - -var_index add_term_undecided(const vector> & coeffs, - const mpq &m_v) { - m_terms.push_back(new lar_term(coeffs, m_v)); - m_orig_terms.push_back(new lar_term(coeffs, m_v)); - return m_terms_start_index + m_terms.size() - 1; -} - -// terms -var_index add_term(const vector> & coeffs, - const mpq &m_v) { - if (strategy_is_undecided()) - return add_term_undecided(coeffs, m_v); - - m_terms.push_back(new lar_term(coeffs, m_v)); - m_orig_terms.push_back(new lar_term(coeffs, m_v)); - unsigned adjusted_term_index = m_terms.size() - 1; - var_index ret = m_terms_start_index + adjusted_term_index; - if (use_tableau() && !coeffs.empty()) { - add_row_for_term(m_orig_terms.back(), ret); - if (m_settings.bound_propagation()) - m_rows_with_changed_bounds.insert(A_r().row_count() - 1); - } - lean_assert(m_ext_vars_to_columns.size() == A_r().column_count()); - return ret; -} - -void add_row_for_term(const lar_term * term, unsigned term_ext_index) { - lean_assert(sizes_are_correct()); - add_row_from_term_no_constraint(term, term_ext_index); - lean_assert(sizes_are_correct()); -} - -void add_row_from_term_no_constraint(const lar_term * term, unsigned term_ext_index) { - register_new_ext_var_index(term_ext_index); - // j will be a new variable - unsigned j = A_r().column_count(); - ul_pair ul(j); - m_vars_to_ul_pairs.push_back(ul); - add_basic_var_to_core_fields(); - if (use_tableau()) { - auto it = iterator_on_term_with_basis_var(*term, j); - A_r().fill_last_row_with_pivoting(it, - m_mpq_lar_core_solver.m_r_solver.m_basis_heading); - m_mpq_lar_core_solver.m_r_solver.m_b.resize(A_r().column_count(), zero_of_type()); - } else { - fill_last_row_of_A_r(A_r(), term); - } - m_mpq_lar_core_solver.m_r_x[j] = get_basic_var_value_from_row_directly(A_r().row_count() - 1); - if (use_lu()) - fill_last_row_of_A_d(A_d(), term); -} - -void add_basic_var_to_core_fields() { - bool use_lu = m_mpq_lar_core_solver.need_to_presolve_with_double_solver(); - lean_assert(!use_lu || A_r().column_count() == A_d().column_count()); - m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column); - m_columns_with_changed_bound.increase_size_by_one(); - m_rows_with_changed_bounds.increase_size_by_one(); - add_new_var_to_core_fields_for_mpq(true); - if (use_lu) - add_new_var_to_core_fields_for_doubles(true); -} - -constraint_index add_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side) { - constraint_index ci = m_constraints.size(); - if (!is_term(j)) { // j is a var - auto vc = new lar_var_constraint(j, kind, right_side); - m_constraints.push_back(vc); - update_column_type_and_bound(j, kind, right_side, ci); - } else { - add_var_bound_on_constraint_for_term(j, kind, right_side, ci); - } - lean_assert(sizes_are_correct()); - return ci; -} - -void update_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index) { - switch(m_mpq_lar_core_solver.m_column_types[j]) { - case column_type::free_column: - update_free_column_type_and_bound(j, kind, right_side, constr_index); - break; - case column_type::boxed: - update_boxed_column_type_and_bound(j, kind, right_side, constr_index); - break; - case column_type::low_bound: - update_low_bound_column_type_and_bound(j, kind, right_side, constr_index); - break; - case column_type::upper_bound: - update_upper_bound_column_type_and_bound(j, kind, right_side, constr_index); - break; - case column_type::fixed: - update_fixed_column_type_and_bound(j, kind, right_side, constr_index); - break; - default: - lean_assert(false); // cannot be here - } -} - -void add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lean_assert(is_term(j)); - unsigned adjusted_term_index = adjust_term_index(j); - unsigned term_j; - if (try_get_val(m_ext_vars_to_columns, j, term_j)) { - mpq rs = right_side - m_orig_terms[adjusted_term_index]->m_v; - m_constraints.push_back(new lar_term_constraint(m_orig_terms[adjusted_term_index], kind, right_side)); - update_column_type_and_bound(term_j, kind, rs, ci); - } - else { - add_constraint_from_term_and_create_new_column_row(j, m_orig_terms[adjusted_term_index], kind, right_side); - } -} - - -void add_constraint_from_term_and_create_new_column_row(unsigned term_j, const lar_term* term, - lconstraint_kind kind, const mpq & right_side) { - - add_row_from_term_no_constraint(term, term_j); - unsigned j = A_r().column_count() - 1; - update_column_type_and_bound(j, kind, right_side - term->m_v, m_constraints.size()); - m_constraints.push_back(new lar_term_constraint(term, kind, right_side)); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); -} - -void decide_on_strategy_and_adjust_initial_state() { - lean_assert(strategy_is_undecided()); - if (m_vars_to_ul_pairs.size() > m_settings.column_number_threshold_for_using_lu_in_lar_solver) { - m_settings.simplex_strategy() = simplex_strategy_enum::lu; - } else { - m_settings.simplex_strategy() = simplex_strategy_enum::tableau_rows; // todo: when to switch to tableau_costs? - } - adjust_initial_state(); -} - -void adjust_initial_state() { - switch (m_settings.simplex_strategy()) { - case simplex_strategy_enum::lu: - adjust_initial_state_for_lu(); - break; - case simplex_strategy_enum::tableau_rows: - adjust_initial_state_for_tableau_rows(); - break; - case simplex_strategy_enum::tableau_costs: - lean_assert(false); // not implemented - case simplex_strategy_enum::undecided: - adjust_initial_state_for_tableau_rows(); - break; - } -} - -void adjust_initial_state_for_lu() { - copy_from_mpq_matrix(A_d()); - unsigned n = A_d().column_count(); - m_mpq_lar_core_solver.m_d_x.resize(n); - m_mpq_lar_core_solver.m_d_low_bounds.resize(n); - m_mpq_lar_core_solver.m_d_upper_bounds.resize(n); - m_mpq_lar_core_solver.m_d_heading = m_mpq_lar_core_solver.m_r_heading; - m_mpq_lar_core_solver.m_d_basis = m_mpq_lar_core_solver.m_r_basis; - - /* - unsigned j = A_d().column_count(); - A_d().add_column(); - lean_assert(m_mpq_lar_core_solver.m_d_x.size() == j); - // lean_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 - 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_upper_bounds.resize(j + 1); - lean_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) { - A_d().add_row(); - m_mpq_lar_core_solver.m_d_heading.push_back(m_mpq_lar_core_solver.m_d_basis.size()); - m_mpq_lar_core_solver.m_d_basis.push_back(j); - }else { - m_mpq_lar_core_solver.m_d_heading.push_back(- static_cast(m_mpq_lar_core_solver.m_d_nbasis.size()) - 1); - m_mpq_lar_core_solver.m_d_nbasis.push_back(j); - }*/ -} - -void adjust_initial_state_for_tableau_rows() { - for (unsigned j = 0; j < m_terms.size(); j++) { - if (contains(m_ext_vars_to_columns, j + m_terms_start_index)) - continue; - add_row_from_term_no_constraint(m_terms[j], j + m_terms_start_index); - } -} - -// this fills the last row of A_d and sets the basis column: -1 in the last column of the row -void fill_last_row_of_A_d(static_matrix & A, const lar_term* ls) { - lean_assert(A.row_count() > 0); - lean_assert(A.column_count() > 0); - unsigned last_row = A.row_count() - 1; - lean_assert(A.m_rows[last_row].empty()); - - for (auto & t : ls->m_coeffs) { - lean_assert(!is_zero(t.second)); - var_index j = t.first; - A.set(last_row, j, - t.second.get_double()); - } - - unsigned basis_j = A.column_count() - 1; - A.set(last_row, basis_j, - 1 ); -} - -void update_free_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_ind) { - mpq y_of_bound(0); - switch (kind) { - case LT: - y_of_bound = -1; - case LE: - m_mpq_lar_core_solver.m_column_types[j] = column_type::upper_bound; - lean_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound); - lean_assert(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j); - { - auto up = numeric_pair(right_side, y_of_bound); - m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; - } - set_upper_bound_witness(j, constr_ind); - break; - case GT: - y_of_bound = 1; - case GE: - m_mpq_lar_core_solver.m_column_types[j] = column_type::low_bound; - lean_assert(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j); - { - auto low = numeric_pair(right_side, y_of_bound); - m_mpq_lar_core_solver.m_r_low_bounds[j] = low; - } - set_low_bound_witness(j, constr_ind); - break; - case EQ: - m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; - m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = numeric_pair(right_side, zero_of_type()); - set_upper_bound_witness(j, constr_ind); - set_low_bound_witness(j, constr_ind); - break; - - default: - lean_unreachable(); - - } - m_columns_with_changed_bound.insert(j); -} - -void update_upper_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lean_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound); - mpq y_of_bound(0); - switch (kind) { - case LT: - y_of_bound = -1; - case LE: - { - auto up = numeric_pair(right_side, y_of_bound); - if (up < m_mpq_lar_core_solver.m_r_upper_bounds()[j]) { - m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; - set_upper_bound_witness(j, ci); - m_columns_with_changed_bound.insert(j); - } - } - break; - case GT: - y_of_bound = 1; - case GE: - m_mpq_lar_core_solver.m_column_types[j] = column_type::boxed; - { - auto low = numeric_pair(right_side, y_of_bound); - m_mpq_lar_core_solver.m_r_low_bounds[j] = low; - set_low_bound_witness(j, ci); - m_columns_with_changed_bound.insert(j); - if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index = j; - } else { - m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j]? column_type::boxed : column_type::fixed; - } - } - break; - case EQ: - { - auto v = numeric_pair(right_side, zero_of_type()); - if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; - set_low_bound_witness(j, ci); - m_infeasible_column_index = j; - } else { - m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; - m_columns_with_changed_bound.insert(j); - set_low_bound_witness(j, ci); - set_upper_bound_witness(j, ci); - m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; - } - break; - } - break; - - default: - lean_unreachable(); - - } -} - -void update_boxed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lean_assert(m_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])); - mpq y_of_bound(0); - switch (kind) { - case LT: - y_of_bound = -1; - case LE: - { - auto up = numeric_pair(right_side, y_of_bound); - if (up < m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; - set_upper_bound_witness(j, ci); - m_columns_with_changed_bound.insert(j); - } - - if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; - lean_assert(false); - m_infeasible_column_index = j; - } else { - if (m_mpq_lar_core_solver.m_r_low_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j]) - m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; - } - } - break; - case GT: - y_of_bound = 1; - case GE: - { - auto low = numeric_pair(right_side, y_of_bound); - if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_mpq_lar_core_solver.m_r_low_bounds[j] = low; - m_columns_with_changed_bound.insert(j); - set_low_bound_witness(j, ci); - } - if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index = j; - } else if ( low == m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; - } - } - break; - case EQ: - { - auto v = numeric_pair(right_side, zero_of_type()); - if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index = j; - set_upper_bound_witness(j, ci); - } else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index = j; - set_low_bound_witness(j, ci); - } else { - m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; - set_low_bound_witness(j, ci); - set_upper_bound_witness(j, ci); - m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; - m_columns_with_changed_bound.insert(j); - } - - break; - } - - default: - lean_unreachable(); - - } -} -void update_low_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lean_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::low_bound); - mpq y_of_bound(0); - switch (kind) { - case LT: - y_of_bound = -1; - case LE: - { - auto up = numeric_pair(right_side, y_of_bound); - m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; - set_upper_bound_witness(j, ci); - m_columns_with_changed_bound.insert(j); - - if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index = j; - } else { - m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j]? column_type::boxed : column_type::fixed; - } - } - break; - case GT: - y_of_bound = 1; - case GE: - { - auto low = numeric_pair(right_side, y_of_bound); - if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_mpq_lar_core_solver.m_r_low_bounds[j] = low; - m_columns_with_changed_bound.insert(j); - set_low_bound_witness(j, ci); - } - } - break; - case EQ: - { - auto v = numeric_pair(right_side, zero_of_type()); - if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index = j; - set_upper_bound_witness(j, ci); - } else { - m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; - set_low_bound_witness(j, ci); - set_upper_bound_witness(j, ci); - m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; - } - m_columns_with_changed_bound.insert(j); - break; - } - - default: - lean_unreachable(); - - } -} - -void update_fixed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lean_assert(m_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])); - lean_assert(m_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())); - auto v = numeric_pair(right_side, mpq(0)); - - mpq y_of_bound(0); - switch (kind) { - case LT: - if (v <= m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index = j; - set_upper_bound_witness(j, ci); - } - break; - case LE: - { - if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index = j; - set_upper_bound_witness(j, ci); - } - } - break; - case GT: - { - if (v >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index =j; - set_low_bound_witness(j, ci); - } - } - break; - case GE: - { - if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index = j; - set_low_bound_witness(j, ci); - } - } - break; - case EQ: - { - if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index = j; - set_upper_bound_witness(j, ci); - } else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; - m_infeasible_column_index = j; - set_low_bound_witness(j, ci); - } - break; - } - - default: - lean_unreachable(); - - } -} - diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp new file mode 100644 index 000000000..e617a1e29 --- /dev/null +++ b/src/util/lp/int_solver.cpp @@ -0,0 +1,606 @@ +/* + Copyright (c) 2017 Microsoft Corporation + Author: Lev Nachmanson +*/ + +#include "util/lp/int_solver.h" +#include "util/lp/lar_solver.h" +namespace lean { + +void int_solver::fix_non_base_columns() { + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + for (unsigned j : lcs.m_r_nbasis) { + if (column_is_int_inf(j)) { + set_value(j, floor(lcs.m_r_x[j].x)); + } + } + if (m_lar_solver->find_feasible_solution() == INFEASIBLE) + failed(); +} + +void int_solver::failed() { + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + + for (unsigned j : m_old_values_set.m_index) { + lcs.m_r_x[j] = m_old_values_data[j]; + lean_assert(lcs.m_r_solver.column_is_feasible(j)); + lcs.m_r_solver.remove_column_from_inf_set(j); + } + lean_assert(lcs.m_r_solver.calc_current_x_is_feasible_include_non_basis()); + lean_assert(lcs.m_r_solver.current_x_is_feasible()); + m_old_values_set.clear(); +} + +void int_solver::trace_inf_rows() const { + unsigned num = m_lar_solver->A_r().column_count(); + for (unsigned v = 0; v < num; v++) { + if (is_int(v) && !get_value(v).is_int()) { + display_column(tout, v); + } + } + + num = 0; + for (unsigned i = 0; i < m_lar_solver->A_r().row_count(); i++) { + unsigned j = m_lar_solver->m_mpq_lar_core_solver.m_r_basis[i]; + if (column_is_int_inf(j)) { + num++; + iterator_on_row it(m_lar_solver->A_r().m_rows[i]); + m_lar_solver->print_linear_iterator(&it, tout); + tout << "\n"; + } + } + tout << "num of int infeasible: " << num << "\n"; +} + +int int_solver::find_inf_int_base_column() { + if (m_inf_int_set.is_empty()) + return -1; + int j = find_inf_int_boxed_base_column_with_smallest_range(); + if (j != -1) + return j; + unsigned k = settings().random_next() % m_inf_int_set.m_index.size(); + return m_inf_int_set.m_index[k]; +} + +int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { + int result = -1; + mpq range; + mpq new_range; + mpq small_range_thresold(1024); + unsigned n = 0; + lar_core_solver & lcs = m_lar_solver->m_mpq_lar_core_solver; + + for (int j : m_inf_int_set.m_index) { + lean_assert(is_base(j) && column_is_int_inf(j)); + if (!is_boxed(j)) + continue; + new_range = lcs.m_r_upper_bounds()[j].x - lcs.m_r_low_bounds()[j].x; + if (new_range > small_range_thresold) + continue; + if (result == -1) { + result = j; + range = new_range; + n = 1; + continue; + } + if (new_range < range) { + n = 1; + result = j; + range = new_range; + continue; + } + if (new_range == range) { + n++; + if (settings().random_next() % n == 0) { + result = j; + continue; + } + } + } + return result; + +} + +lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { + lean_assert(is_feasible()); + init_inf_int_set(); + lean_assert(inf_int_set_is_correct()); + // currently it is a reimplementation of + // final_check_status theory_arith::check_int_feasibility() + // from theory_arith_int.h + if (m_lar_solver->model_is_int_feasible()) + return lia_move::ok; + if (!gcd_test(ex)) + return lia_move::conflict; + /* + if (m_params.m_arith_euclidean_solver) + apply_euclidean_solver(); + + */ + m_lar_solver->pivot_fixed_vars_from_basis(); + patch_int_infeasible_columns(); + fix_non_base_columns(); + lean_assert(is_feasible()); + TRACE("arith_int_rows", trace_inf_rows();); + + if (find_inf_int_base_column() == -1) + return lia_move::ok; + + + if ((++m_branch_cut_counter) % settings().m_int_branch_cut_threshold == 0) { + move_non_base_vars_to_bounds(); + /* + if (!make_feasible()) { + TRACE("arith_int", tout << "failed to move variables to bounds.\n";); + failed(); + return FC_CONTINUE; + } + int int_var = find_inf_int_base_var(); + if (int_var != null_int) { + TRACE("arith_int", tout << "v" << int_var << " does not have an integer assignment: " << get_value(int_var) << "\n";); + SASSERT(is_base(int_var)); + row const & r = m_rows[get_var_row(int_var)]; + if (!mk_gomory_cut(r)) { + // silent failure + } + return FC_CONTINUE; + }*/ + } + else { + int j = find_inf_int_base_column(); + /* + if (j != -1) { + TRACE("arith_int", tout << "v" << j << " does not have an integer assignment: " << get_value(j) << "\n";); + // apply branching + branch_infeasible_int_var(int_var); + return false; + }*/ + } + // return true; + return lia_move::give_up; +} + +void int_solver::move_non_base_vars_to_bounds() { + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + for (unsigned j : lcs.m_r_nbasis) { + auto & val = lcs.m_r_x[j]; + switch (lcs.m_column_types()[j]) { + case column_type::boxed: + if (val != lcs.m_r_low_bounds()[j] && val != lcs.m_r_upper_bounds()[j]) + set_value(j, lcs.m_r_low_bounds()[j]); + break; + case column_type::low_bound: + if (val != lcs.m_r_low_bounds()[j]) + set_value(j, lcs.m_r_low_bounds()[j]); + break; + case column_type::upper_bound: + if (val != lcs.m_r_upper_bounds()[j]) + set_value(j, lcs.m_r_upper_bounds()[j]); + break; + default: + if (is_int(j) && !val.is_int()) { + set_value(j, impq(floor(val))); + } + } + } +} + + + +void int_solver::set_value(unsigned j, const impq & new_val) { + auto & x = m_lar_solver->m_mpq_lar_core_solver.m_r_x[j]; + if (!m_old_values_set.contains(j)) { + m_old_values_set.insert(j); + m_old_values_data[j] = x; + } + auto delta = new_val - x; + x = new_val; + m_lar_solver->change_basic_x_by_delta_on_column(j, delta); + update_column_in_inf_set_set(j); +} + +void int_solver::patch_int_infeasible_columns() { + bool inf_l, inf_u; + impq l, u; + mpq m; + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + for (unsigned j : lcs.m_r_nbasis) { + if (!is_int(j)) + continue; + get_freedom_interval_for_column(j, inf_l, l, inf_u, u, m); + impq & val = lcs.m_r_x[j]; + bool val_is_int = val.is_int(); + bool m_is_one = m.is_one(); + if (m.is_one() && val_is_int) + continue; + // check whether value of j is already a multiple of m. + if (val_is_int && (val.x / m).is_int()) + continue; + TRACE("patch_int", + tout << "TARGET j" << j << " -> ["; + if (inf_l) tout << "-oo"; else tout << l; + tout << ", "; + if (inf_u) tout << "oo"; else tout << u; + tout << "]"; + tout << ", m: " << m << ", val: " << val << ", is_int: " << m_lar_solver->column_is_int(j) << "\n";); + if (!inf_l) { + l = m_is_one? ceil(l) : m * ceil(l / m); + if (inf_u || l <= u) { + TRACE("patch_int", + tout << "patching with l: " << l << '\n';); + + set_value(j, l); + } else { + TRACE("patch_int", + tout << "not patching " << l << "\n";); + } + } else if (!inf_u) { + u = m_is_one? floor(u) : m * floor(u / m); + set_value(j, u); + TRACE("patch_int", + tout << "patching with u: " << u << '\n';); + } else { + set_value(j, impq(0)); + TRACE("patch_int", + tout << "patching with 0\n";); + } + } +} + +mpq get_denominators_lcm(iterator_on_row &it) { + mpq r(1); + mpq a; + unsigned j; + while (it.next(a, j)) { + r = lcm(r, denominator(a)); + } + return r; +} + +bool int_solver::gcd_test_for_row(static_matrix> & A, unsigned i, explanation & ex) { + iterator_on_row it(A.m_rows[i]); + std::cout << "gcd_test_for_row(" << i << ")\n"; + mpq lcm_den = get_denominators_lcm(it); + mpq consts(0); + mpq gcds(0); + mpq least_coeff(0); + bool least_coeff_is_bounded = false; + mpq a; + unsigned j; + while (it.next(a, j)) { + if (m_lar_solver->column_is_fixed(j)) { + mpq aux = lcm_den * a; + consts += aux * m_lar_solver->column_low_bound(j).x; + } + else if (m_lar_solver->column_is_real(j)) { + return true; + } + else if (gcds.is_zero()) { + gcds = abs(lcm_den * a); + least_coeff = gcds; + least_coeff_is_bounded = m_lar_solver->column_is_bounded(j); + } + else { + mpq aux = abs(lcm_den * a); + gcds = gcd(gcds, aux); + if (aux < least_coeff) { + least_coeff = aux; + least_coeff_is_bounded = m_lar_solver->column_is_bounded(j); + } + else if (least_coeff_is_bounded && aux == least_coeff) { + least_coeff_is_bounded = m_lar_solver->column_is_bounded(j); + } + } + SASSERT(gcds.is_int()); + SASSERT(least_coeff.is_int()); + TRACE("gcd_test_bug", tout << "coeff: " << a << ", gcds: " << gcds + << " least_coeff: " << least_coeff << " consts: " << consts << "\n";); + + } + + if (gcds.is_zero()) { + // All variables are fixed. + // This theory guarantees that the assignment satisfies each row, and + // fixed integer variables are assigned to integer values. + return true; + } + + if (!(consts / gcds).is_int()) + fill_explanation_from_fixed_columns(it, ex); + + if (least_coeff.is_one() && !least_coeff_is_bounded) { + SASSERT(gcds.is_one()); + return true; + } + + if (least_coeff_is_bounded) { + return ext_gcd_test(it, least_coeff, lcm_den, consts, ex); + } + return true; +} + +void int_solver::add_to_explanation_from_fixed_or_boxed_column(unsigned j, explanation & ex) { + constraint_index lc, uc; + m_lar_solver->get_bound_constraint_witnesses_for_column(j, lc, uc); + ex.m_explanation.push_back(std::make_pair(mpq(1), lc)); + ex.m_explanation.push_back(std::make_pair(mpq(1), uc)); +} +void int_solver::fill_explanation_from_fixed_columns(iterator_on_row & it, explanation & ex) { + it.reset(); + unsigned j; + while (it.next(j)) { + if (!m_lar_solver->column_is_fixed(j)) + continue; + add_to_explanation_from_fixed_or_boxed_column(j, ex); + } +} + +bool int_solver::gcd_test(explanation & ex) { + auto & A = m_lar_solver->A_r(); // getting the matrix + for (unsigned i = 0; i < A.row_count(); i++) + if (!gcd_test_for_row(A, i, ex)) { + std::cout << "false from gcd_test\n" ; + return false; + } + + return true; +} + +bool int_solver::ext_gcd_test(iterator_on_row & it, + mpq const & least_coeff, + mpq const & lcm_den, + mpq const & consts, explanation& ex) { + + std::cout << "calling ext_gcd_test" << std::endl; + mpq gcds(0); + mpq l(consts); + mpq u(consts); + + it.reset(); + mpq a; + unsigned j; + while (it.next(a, j)) { + if (m_lar_solver->column_is_fixed(j)) + continue; + SASSERT(!m_lar_solver->column_is_real(j)); + mpq ncoeff = lcm_den * a; + SASSERT(ncoeff.is_int()); + mpq abs_ncoeff = abs(ncoeff); + if (abs_ncoeff == least_coeff) { + SASSERT(m_lar_solver->column_is_bounded(j)); + if (ncoeff.is_pos()) { + // l += ncoeff * m_lar_solver->column_low_bound(j).x; + l.addmul(ncoeff, m_lar_solver->column_low_bound(j).x); + // u += ncoeff * m_lar_solver->column_upper_bound(j).x; + u.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x); + } + else { + // l += ncoeff * upper_bound(j).get_rational(); + l.addmul(ncoeff, m_lar_solver->column_upper_bound(j).x); + // u += ncoeff * lower_bound(j).get_rational(); + u.addmul(ncoeff, m_lar_solver->column_low_bound(j).x); + } + add_to_explanation_from_fixed_or_boxed_column(j, ex); + } + else if (gcds.is_zero()) { + gcds = abs_ncoeff; + } + else { + gcds = gcd(gcds, abs_ncoeff); + } + SASSERT(gcds.is_int()); + } + + if (gcds.is_zero()) { + return true; + } + + mpq l1 = ceil(l/gcds); + mpq u1 = floor(u/gcds); + + if (u1 < l1) { + fill_explanation_from_fixed_columns(it, ex); + return false; + } + + return true; + +} + +linear_combination_iterator * int_solver::get_column_iterator(unsigned j) { + if (m_lar_solver->use_tableau()) + return new iterator_on_column(m_lar_solver->A_r().m_columns[j], m_lar_solver->A_r()); + return new iterator_on_indexed_vector(m_lar_solver->get_column_in_lu_mode(j)); +} + + +int_solver::int_solver(lar_solver* lar_slv) : + m_lar_solver(lar_slv), + m_branch_cut_counter(0) { + lean_assert(m_old_values_set.size() == 0); + m_old_values_set.resize(lar_slv->A_r().column_count()); + m_old_values_data.resize(lar_slv->A_r().column_count(), zero_of_type()); +} + +bool int_solver::lower(unsigned j) const { + switch (m_lar_solver->m_mpq_lar_core_solver.m_column_types()[j]) { + case column_type::fixed: + case column_type::boxed: + case column_type::low_bound: + return true; + default: + return false; + } +} + +bool int_solver::upper(unsigned j) const { + switch (m_lar_solver->m_mpq_lar_core_solver.m_column_types()[j]) { + case column_type::fixed: + case column_type::boxed: + case column_type::upper_bound: + return true; + default: + return false; + } +} + +const impq& int_solver::lower_bound(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_r_low_bounds()[j]; +} + +const impq& int_solver::upper_bound(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_r_upper_bounds()[j]; +} + + +void set_lower(impq & l, + bool & inf_l, + impq const & v ) { + if (inf_l || v > l) { + l = v; + inf_l = false; + } +} + +void set_upper(impq & u, + bool & inf_u, + impq const & v) { + if (inf_u || v < u) { + u = v; + inf_u = false; + } +} + +bool int_solver::get_freedom_interval_for_column(unsigned x_j, bool & inf_l, impq & l, bool & inf_u, impq & u, mpq & m) { + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + if (lcs.m_r_heading[x_j] >= 0) // the basic var + return false; + + impq const & x_j_val = lcs.m_r_x[x_j]; + linear_combination_iterator *it = get_column_iterator(x_j); + + inf_l = true; + inf_u = true; + l = u = zero_of_type(); + m = mpq(1); + + if (lower(x_j)) { + set_lower(l, inf_l, lower_bound(x_j)); + } + if (upper(x_j)) { + set_upper(u, inf_u, upper_bound(x_j)); + } + + mpq a_ij; unsigned i; + while (it->next(a_ij, i)) { + unsigned x_i = lcs.m_r_basis[i]; + impq const & x_i_val = lcs.m_r_x[x_i]; + if (is_int(x_i) && is_int(x_j) && !a_ij.is_int()) + m = lcm(m, denominator(a_ij)); + bool x_i_lower = lower(x_i); + bool x_i_upper = upper(x_i); + if (a_ij.is_neg()) { + if (x_i_lower) { + impq new_l = x_j_val + ((x_i_val - lcs.m_r_low_bounds()[x_i]) / a_ij); + set_lower(l, inf_l, new_l); + if (!inf_l && !inf_u && l == u) break;; + } + if (x_i_upper) { + impq new_u = x_j_val + ((x_i_val - lcs.m_r_upper_bounds()[x_i]) / a_ij); + set_upper(u, inf_u, new_u); + if (!inf_l && !inf_u && l == u) break;; + } + } + else { + if (x_i_upper) { + impq new_l = x_j_val + ((x_i_val - lcs.m_r_upper_bounds()[x_i]) / a_ij); + set_lower(l, inf_u, new_l); + if (!inf_l && !inf_u && l == u) break;; + } + if (x_i_lower) { + impq new_u = x_j_val + ((x_i_val - lcs.m_r_low_bounds()[x_i]) / a_ij); + set_upper(u, inf_u, new_u); + if (!inf_l && !inf_u && l == u) break;; + } + } + } + + delete it; + TRACE("freedom_interval", + tout << "freedom variable for:\n"; + tout << m_lar_solver->get_column_name(x_j); + tout << "["; + if (inf_l) tout << "-oo"; else tout << l; + tout << "; "; + if (inf_u) tout << "oo"; else tout << u; + tout << "]\n";); + return true; + +} + +bool int_solver::is_int(unsigned j) const { + return m_lar_solver->column_is_int(j); +} + +bool int_solver::value_is_int(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_r_x[j].is_int(); +} + + + +bool int_solver::is_feasible() const { + auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + lean_assert( + lcs.m_r_solver.calc_current_x_is_feasible_include_non_basis() == + lcs.m_r_solver.current_x_is_feasible()); + return lcs.m_r_solver.current_x_is_feasible(); +} +const impq & int_solver::get_value(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_r_x[j]; +} + +void int_solver::display_column(std::ostream & out, unsigned j) const { + m_lar_solver->m_mpq_lar_core_solver.m_r_solver.print_column_info(j, out); +} + +bool int_solver::inf_int_set_is_correct() const { + for (unsigned j = 0; j < m_lar_solver->A_r().column_count(); j++) { + if (m_inf_int_set.contains(j) != is_int(j) && (!value_is_int(j))) + return false; + } + return true; +} + +bool int_solver::column_is_int_inf(unsigned j) const { + return is_int(j) && (!value_is_int(j)); +} + +void int_solver::init_inf_int_set() { + m_inf_int_set.clear(); + m_inf_int_set.resize(m_lar_solver->A_r().column_count()); + for (unsigned j : m_lar_solver->m_mpq_lar_core_solver.m_r_basis) { + if (column_is_int_inf(j)) + m_inf_int_set.insert(j); + } +} + +void int_solver::update_column_in_inf_set_set(unsigned j) { + if (is_int(j) && (!value_is_int(j))) + m_inf_int_set.insert(j); + else + m_inf_int_set.erase(j); +} + +bool int_solver::is_base(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_r_heading[j] >= 0; +} + +bool int_solver::is_boxed(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_column_types[j] == column_type::boxed; +} + +lp_settings& int_solver::settings() { + return m_lar_solver->settings(); +} + +} diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h new file mode 100644 index 000000000..981127bc8 --- /dev/null +++ b/src/util/lp/int_solver.h @@ -0,0 +1,100 @@ +/* + Copyright (c) 2017 Microsoft Corporation + Author: Lev Nachmanson +*/ +#pragma once +#include "util/lp/lp_settings.h" +#include "util/lp/static_matrix.h" +#include "util/lp/iterator_on_row.h" +#include "util/lp/int_set.h" +#include "util/lp/lar_term.h" + +namespace lean { +class lar_solver; +template +struct lp_constraint; +enum class lia_move { + ok, + branch, + cut, + conflict, + give_up +}; + +struct explanation { + vector> m_explanation; +}; + +class int_solver { +public: + // fields + lar_solver *m_lar_solver; + int_set m_old_values_set; + vector m_old_values_data; + int_set m_inf_int_set; + unsigned m_branch_cut_counter; + // methods + int_solver(lar_solver* lp); + // main function to check that solution provided by lar_solver is valid for integral values, + // or provide a way of how it can be adjusted. + lia_move check(lar_term& t, mpq& k, explanation& ex); +private: + + // how to tighten bounds for integer variables. + + bool gcd_test_for_row(static_matrix> & A, unsigned i, explanation &); + + // gcd test + // 5*x + 3*y + 6*z = 5 + // suppose x is fixed at 2. + // so we have 10 + 3(y + 2z) = 5 + // 5 = -3(y + 2z) + // this is unsolvable because 5/3 is not an integer. + // so we create a lemma that rules out this condition. + // + bool gcd_test(explanation & ); // returns false in case of failure. Creates a theory lemma in case of failure. + + // create goromy cuts + // either creates a conflict or a bound. + + // branch and bound: + // decide what to branch and bound on + // creates a fresh inequality. + + bool branch(const lp_constraint & new_inequality); + bool ext_gcd_test(iterator_on_row & it, + mpq const & least_coeff, + mpq const & lcm_den, + mpq const & consts, + explanation & ex); + void fill_explanation_from_fixed_columns(iterator_on_row & it, explanation &); + void add_to_explanation_from_fixed_or_boxed_column(unsigned j, explanation &); + void remove_fixed_vars_from_base(); + void patch_int_infeasible_columns(); + bool get_freedom_interval_for_column(unsigned j, bool & inf_l, impq & l, bool & inf_u, impq & u, mpq & m); + linear_combination_iterator * get_column_iterator(unsigned j); + bool lower(unsigned j) const; + bool upper(unsigned j) const; + const impq & lower_bound(unsigned j) const; + const impq & upper_bound(unsigned j) const; + bool is_int(unsigned j) const; + bool is_base(unsigned j) const; + bool is_boxed(unsigned j) const; + bool value_is_int(unsigned j) const; + void set_value(unsigned j, const impq & new_val); + void fix_non_base_columns(); + void failed(); + bool is_feasible() const; + const impq & get_value(unsigned j) const; + void display_column(std::ostream & out, unsigned j) const; + bool inf_int_set_is_correct() const; + void init_inf_int_set(); + void update_column_in_inf_set_set(unsigned j); + bool column_is_int_inf(unsigned j) const; + void trace_inf_rows() const; + int find_inf_int_base_column(); + int find_inf_int_boxed_base_column_with_smallest_range(); + lp_settings& settings(); + void move_non_base_vars_to_bounds(); +}; +} diff --git a/src/util/lp/lar_core_solver.h b/src/util/lp/lar_core_solver.h index 71d69c3a4..44a6349a7 100644 --- a/src/util/lp/lar_core_solver.h +++ b/src/util/lp/lar_core_solver.h @@ -796,6 +796,37 @@ public: return new iterator_on_indexed_vector(m_r_solver.m_ed); } } + + bool column_is_fixed(unsigned j) const { + return m_column_types()[j] == column_type::fixed || + ( m_column_types()[j] == column_type::boxed && + m_r_solver.m_low_bounds[j] == m_r_solver.m_upper_bounds[j]); + } + + const impq & low_bound(unsigned j) const { + lean_assert(m_column_types()[j] == column_type::fixed || + m_column_types()[j] == column_type::boxed || + m_column_types()[j] == column_type::low_bound); + return m_r_low_bounds[j]; + } + + const impq & upper_bound(unsigned j) const { + lean_assert(m_column_types()[j] == column_type::fixed || + m_column_types()[j] == column_type::boxed || + m_column_types()[j] == column_type::upper_bound); + return m_r_upper_bounds[j]; + } + + const bool column_is_bounded(unsigned j) const { + switch(m_column_types()[j]) { + case column_type::fixed: + case column_type::boxed: + return true; + default: + return false; + } + } + }; } diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp new file mode 100644 index 000000000..def72734c --- /dev/null +++ b/src/util/lp/lar_solver.cpp @@ -0,0 +1,2040 @@ +#include "util/lp/lar_solver.h" +/* + Copyright (c) 2017 Microsoft Corporation + Author: Lev Nachmanson +*/ + +namespace lean { + +unsigned lar_solver::constraint_count() const { + return m_constraints.size(); +} +const lar_base_constraint& lar_solver::get_constraint(unsigned ci) const { + return *(m_constraints[ci]); +} + +////////////////// methods //////////////////////////////// +static_matrix> & lar_solver::A_r() { return m_mpq_lar_core_solver.m_r_A;} +static_matrix> const & lar_solver::A_r() const { return m_mpq_lar_core_solver.m_r_A;} +static_matrix & lar_solver::A_d() { return m_mpq_lar_core_solver.m_d_A;} +static_matrix const & lar_solver::A_d() const { return m_mpq_lar_core_solver.m_d_A;} + +lp_settings & lar_solver::settings() { return m_settings;} + +lp_settings const & lar_solver::settings() const { return m_settings;} + +void clear() {lean_assert(false); // not implemented +} + + +lar_solver::lar_solver() : m_status(OPTIMAL), + m_infeasible_column_index(-1), + m_terms_start_index(1000000), + m_mpq_lar_core_solver(m_settings, *this) +{ +} + +void lar_solver::set_propagate_bounds_on_pivoted_rows_mode(bool v) { + m_mpq_lar_core_solver.m_r_solver.m_pivoted_rows = v? (& m_rows_with_changed_bounds) : nullptr; +} + +lar_solver::~lar_solver(){ + for (auto c : m_constraints) + delete c; + for (auto t : m_terms) + delete t; +} + +numeric_pair const& lar_solver::get_value(var_index vi) const { return m_mpq_lar_core_solver.m_r_x[vi]; } + +bool lar_solver::is_term(var_index j) const { + return j >= m_terms_start_index && j - m_terms_start_index < m_terms.size(); +} + +unsigned lar_solver::adjust_term_index(unsigned j) const { + lean_assert(is_term(j)); + return j - m_terms_start_index; +} + + +bool lar_solver::use_lu() const { return m_settings.simplex_strategy() == simplex_strategy_enum::lu; } + +bool lar_solver::sizes_are_correct() const { + lean_assert(strategy_is_undecided() || !m_mpq_lar_core_solver.need_to_presolve_with_double_solver() || A_r().column_count() == A_d().column_count()); + lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_column_types.size()); + lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_x.size()); + return true; +} + + +void lar_solver::print_implied_bound(const implied_bound& be, std::ostream & out) const { + out << "implied bound\n"; + unsigned v = be.m_j; + if (is_term(v)) { + out << "it is a term number " << be.m_j << std::endl; + print_term(*m_terms[be.m_j - m_terms_start_index], out); + } + else { + out << get_column_name(v); + } + out << " " << lconstraint_kind_string(be.kind()) << " " << be.m_bound << std::endl; + // for (auto & p : be.m_explanation) { + // out << p.first << " : "; + // print_constraint(p.second, out); + // } + + // m_mpq_lar_core_solver.m_r_solver.print_column_info(be.m_j< m_terms_start_index? be.m_j : adjust_term_index(be.m_j), out); + out << "end of implied bound" << std::endl; +} + +bool lar_solver::implied_bound_is_correctly_explained(implied_bound const & be, const vector> & explanation) const { + std::unordered_map coeff_map; + auto rs_of_evidence = zero_of_type(); + unsigned n_of_G = 0, n_of_L = 0; + bool strict = false; + for (auto & it : explanation) { + mpq coeff = it.first; + constraint_index con_ind = it.second; + const auto & constr = *m_constraints[con_ind]; + lconstraint_kind kind = coeff.is_pos() ? constr.m_kind : flip_kind(constr.m_kind); + register_in_map(coeff_map, constr, coeff); + if (kind == GT || kind == LT) + strict = true; + if (kind == GE || kind == GT) n_of_G++; + else if (kind == LE || kind == LT) n_of_L++; + rs_of_evidence += coeff*constr.m_right_side; + } + lean_assert(n_of_G == 0 || n_of_L == 0); + lconstraint_kind kind = n_of_G ? GE : (n_of_L ? LE : EQ); + if (strict) + kind = static_cast((static_cast(kind) / 2)); + + if (!is_term(be.m_j)) { + if (coeff_map.size() != 1) + return false; + auto it = coeff_map.find(be.m_j); + if (it == coeff_map.end()) return false; + mpq ratio = it->second; + if (ratio < zero_of_type()) { + kind = static_cast(-kind); + } + rs_of_evidence /= ratio; + } else { + const lar_term * t = m_terms[adjust_term_index(be.m_j)]; + const auto first_coeff = *t->m_coeffs.begin(); + unsigned j = first_coeff.first; + auto it = coeff_map.find(j); + if (it == coeff_map.end()) + return false; + mpq ratio = it->second / first_coeff.second; + for (auto & p : t->m_coeffs) { + it = coeff_map.find(p.first); + if (it == coeff_map.end()) + return false; + if (p.second * ratio != it->second) + return false; + } + if (ratio < zero_of_type()) { + kind = static_cast(-kind); + } + rs_of_evidence /= ratio; + rs_of_evidence += t->m_v * ratio; + } + + return kind == be.kind() && rs_of_evidence == be.m_bound; +} + + +void lar_solver::analyze_new_bounds_on_row( + unsigned row_index, + bound_propagator & bp) { + lean_assert(!use_tableau()); + iterator_on_pivot_row it(m_mpq_lar_core_solver.get_pivot_row(), m_mpq_lar_core_solver.m_r_basis[row_index]); + + bound_analyzer_on_row ra_pos(it, + zero_of_type>(), + row_index, + bp + ); + ra_pos.analyze(); +} + +void lar_solver::analyze_new_bounds_on_row_tableau( + unsigned row_index, + bound_propagator & bp + ) { + + if (A_r().m_rows[row_index].size() > settings().max_row_length_for_bound_propagation) + return; + iterator_on_row it(A_r().m_rows[row_index]); + lean_assert(use_tableau()); + bound_analyzer_on_row::analyze_row(it, + zero_of_type>(), + row_index, + bp + ); +} + + +void lar_solver::substitute_basis_var_in_terms_for_row(unsigned i) { + // todo : create a map from term basic vars to the rows where they are used + unsigned basis_j = m_mpq_lar_core_solver.m_r_solver.m_basis[i]; + for (unsigned k = 0; k < m_terms.size(); k++) { + if (term_is_used_as_row(k)) + continue; + if (!m_terms[k]->contains(basis_j)) + continue; + m_terms[k]->subst(basis_j, m_mpq_lar_core_solver.m_r_solver.m_pivot_row); + } +} + +void lar_solver::calculate_implied_bounds_for_row(unsigned i, bound_propagator & bp) { + if(use_tableau()) { + analyze_new_bounds_on_row_tableau(i, bp); + } else { + m_mpq_lar_core_solver.calculate_pivot_row(i); + substitute_basis_var_in_terms_for_row(i); + analyze_new_bounds_on_row(i, bp); + } +} + + +linear_combination_iterator * lar_solver::create_new_iter_from_term(unsigned term_index) const { + lean_assert(false); // not implemented + return nullptr; + // new linear_combination_iterator_on_vector(m_terms[adjust_term_index(term_index)]->coeffs_as_vector()); +} + +unsigned lar_solver::adjust_column_index_to_term_index(unsigned j) const { + unsigned ext_var_or_term = m_columns_to_ext_vars_or_term_indices[j]; + return ext_var_or_term < m_terms_start_index ? j : ext_var_or_term; +} + +void lar_solver::propagate_bounds_on_a_term(const lar_term& t, bound_propagator & bp, unsigned term_offset) { + lean_assert(false); // not implemented +} + + +void lar_solver::explain_implied_bound(implied_bound & ib, bound_propagator & bp) { + unsigned i = ib.m_row_or_term_index; + int bound_sign = ib.m_is_low_bound? 1: -1; + int j_sign = (ib.m_coeff_before_j_is_pos ? 1 :-1) * bound_sign; + unsigned m_j = ib.m_j; + if (is_term(m_j)) { + auto it = m_ext_vars_to_columns.find(m_j); + lean_assert(it != m_ext_vars_to_columns.end()); + m_j = it->second.ext_j(); + } + for (auto const& r : A_r().m_rows[i]) { + unsigned j = r.m_j; + mpq const& a = r.get_val(); + if (j == m_j) continue; + if (is_term(j)) { + auto it = m_ext_vars_to_columns.find(j); + lean_assert(it != m_ext_vars_to_columns.end()); + j = it->second.ext_j(); + } + int a_sign = is_pos(a)? 1: -1; + int sign = j_sign * a_sign; + const ul_pair & ul = m_vars_to_ul_pairs[j]; + auto witness = sign > 0? ul.upper_bound_witness(): ul.low_bound_witness(); + lean_assert(is_valid(witness)); + bp.consume(a, witness); + } + // lean_assert(implied_bound_is_correctly_explained(ib, explanation)); +} + + +bool lar_solver::term_is_used_as_row(unsigned term) const { + lean_assert(is_term(term)); + return contains(m_ext_vars_to_columns, term); +} + +void lar_solver::propagate_bounds_on_terms(bound_propagator & bp) { + for (unsigned i = 0; i < m_terms.size(); i++) { + if (term_is_used_as_row(i + m_terms_start_index)) + continue; // this term is used a left side of a constraint, + // it was processed as a touched row if needed + propagate_bounds_on_a_term(*m_terms[i], bp, i); + } +} + + +// goes over touched rows and tries to induce bounds +void lar_solver::propagate_bounds_for_touched_rows(bound_propagator & bp) { + if (!use_tableau()) + return; // todo: consider to remove the restriction + + for (unsigned i : m_rows_with_changed_bounds.m_index) { + calculate_implied_bounds_for_row(i, bp); + } + m_rows_with_changed_bounds.clear(); + if (!use_tableau()) { + propagate_bounds_on_terms(bp); + } +} + +lp_status lar_solver::get_status() const { return m_status;} + +void lar_solver::set_status(lp_status s) {m_status = s;} + +lp_status lar_solver::find_feasible_solution() { + m_settings.st().m_make_feasible++; + if (A_r().column_count() > m_settings.st().m_max_cols) + m_settings.st().m_max_cols = A_r().column_count(); + if (A_r().row_count() > m_settings.st().m_max_rows) + m_settings.st().m_max_rows = A_r().row_count(); + if (strategy_is_undecided()) + decide_on_strategy_and_adjust_initial_state(); + + m_mpq_lar_core_solver.m_r_solver.m_look_for_feasible_solution_only = true; + return solve(); +} + +lp_status lar_solver::solve() { + if (m_status == INFEASIBLE) { + return m_status; + } + solve_with_core_solver(); + if (m_status != INFEASIBLE) { + if (m_settings.bound_propagation()) + detect_rows_with_changed_bounds(); + } + + m_columns_with_changed_bound.clear(); + return m_status; +} + +void lar_solver::fill_explanation_from_infeasible_column(vector> & evidence) const{ + + // this is the case when the lower bound is in conflict with the upper one + const ul_pair & ul = m_vars_to_ul_pairs[m_infeasible_column_index]; + evidence.push_back(std::make_pair(numeric_traits::one(), ul.upper_bound_witness())); + evidence.push_back(std::make_pair(-numeric_traits::one(), ul.low_bound_witness())); +} + + +unsigned lar_solver::get_total_iterations() const { return m_mpq_lar_core_solver.m_r_solver.total_iterations(); } +// see http://research.microsoft.com/projects/z3/smt07.pdf +// This method searches for a feasible solution with as many different values of variables, reverenced in vars, as it can find +// Attention, after a call to this method the non-basic variables don't necesserarly stick to their bounds anymore +vector lar_solver::get_list_of_all_var_indices() const { + vector ret; + for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_heading.size(); j++) + ret.push_back(j); + return ret; +} +void lar_solver::push() { + m_simplex_strategy = m_settings.simplex_strategy(); + m_simplex_strategy.push(); + m_status.push(); + m_vars_to_ul_pairs.push(); + m_infeasible_column_index.push(); + m_mpq_lar_core_solver.push(); + m_term_count = m_terms.size(); + m_term_count.push(); + m_constraint_count = m_constraints.size(); + m_constraint_count.push(); +} + +void lar_solver::clean_large_elements_after_pop(unsigned n, int_set& set) { + vector to_remove; + for (unsigned j: set.m_index) + if (j >= n) + to_remove.push_back(j); + for (unsigned j : to_remove) + set.erase(j); +} + +void lar_solver::shrink_inf_set_after_pop(unsigned n, int_set & set) { + clean_large_elements_after_pop(n, set); + set.resize(n); +} + + +void lar_solver::pop(unsigned k) { + int n_was = static_cast(m_ext_vars_to_columns.size()); + m_status.pop(k); + m_infeasible_column_index.pop(k); + unsigned n = m_vars_to_ul_pairs.peek_size(k); + for (unsigned j = n_was; j-- > n;) + m_ext_vars_to_columns.erase(m_columns_to_ext_vars_or_term_indices[j]); + m_columns_to_ext_vars_or_term_indices.resize(n); + if (m_settings.use_tableau()) { + pop_tableau(); + } + m_vars_to_ul_pairs.pop(k); + + m_mpq_lar_core_solver.pop(k); + clean_large_elements_after_pop(n, m_columns_with_changed_bound); + unsigned m = A_r().row_count(); + clean_large_elements_after_pop(m, m_rows_with_changed_bounds); + clean_inf_set_of_r_solver_after_pop(); + lean_assert(m_settings.simplex_strategy() == simplex_strategy_enum::undecided || + (!use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); + + + lean_assert(ax_is_correct()); + lean_assert(m_mpq_lar_core_solver.m_r_solver.inf_set_is_correct()); + m_constraint_count.pop(k); + for (unsigned i = m_constraint_count; i < m_constraints.size(); i++) + delete m_constraints[i]; + + m_constraints.resize(m_constraint_count); + m_term_count.pop(k); + for (unsigned i = m_term_count; i < m_terms.size(); i++) { + delete m_terms[i]; + } + m_terms.resize(m_term_count); + m_simplex_strategy.pop(k); + m_settings.simplex_strategy() = m_simplex_strategy; + lean_assert(sizes_are_correct()); + lean_assert((!m_settings.use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); +} + +vector lar_solver::get_all_constraint_indices() const { + vector ret; + constraint_index i = 0; + while ( i < m_constraints.size()) + ret.push_back(i++); + return ret; +} + +bool lar_solver::maximize_term_on_tableau(const vector> & term, + impq &term_max) { + if (settings().simplex_strategy() == simplex_strategy_enum::undecided) + decide_on_strategy_and_adjust_initial_state(); + + m_mpq_lar_core_solver.solve(); + if (m_mpq_lar_core_solver.m_r_solver.get_status() == UNBOUNDED) + return false; + + term_max = 0; + for (auto & p : term) + term_max += p.first * m_mpq_lar_core_solver.m_r_x[p.second]; + + return true; +} + +bool lar_solver::costs_are_zeros_for_r_solver() const { + for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_solver.m_costs.size(); j++) { + lean_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_costs[j])); + } + return true; +} +bool lar_solver::reduced_costs_are_zeroes_for_r_solver() const { + for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_solver.m_d.size(); j++) { + lean_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_d[j])); + } + return true; +} + +void lar_solver::set_costs_to_zero(const vector> & term) { + auto & rslv = m_mpq_lar_core_solver.m_r_solver; + auto & jset = m_mpq_lar_core_solver.m_r_solver.m_inf_set; // hijack this set that should be empty right now + lean_assert(jset.m_index.size()==0); + + for (auto & p : term) { + unsigned j = p.second; + rslv.m_costs[j] = zero_of_type(); + int i = rslv.m_basis_heading[j]; + if (i < 0) + jset.insert(j); + else { + for (auto & rc : A_r().m_rows[i]) + jset.insert(rc.m_j); + } + } + + for (unsigned j : jset.m_index) + rslv.m_d[j] = zero_of_type(); + + jset.clear(); + + lean_assert(reduced_costs_are_zeroes_for_r_solver()); + lean_assert(costs_are_zeros_for_r_solver()); +} + +void lar_solver::prepare_costs_for_r_solver(const vector> & term) { + + auto & rslv = m_mpq_lar_core_solver.m_r_solver; + rslv.m_using_infeas_costs = false; + lean_assert(costs_are_zeros_for_r_solver()); + lean_assert(reduced_costs_are_zeroes_for_r_solver()); + rslv.m_costs.resize(A_r().column_count(), zero_of_type()); + for (auto & p : term) { + unsigned j = p.second; + rslv.m_costs[j] = p.first; + if (rslv.m_basis_heading[j] < 0) + rslv.m_d[j] += p.first; + else + rslv.update_reduced_cost_for_basic_column_cost_change(- p.first, j); + } + lean_assert(rslv.reduced_costs_are_correct_tableau()); +} + +bool lar_solver::maximize_term_on_corrected_r_solver(const vector> & term, + impq &term_max) { + settings().backup_costs = false; + switch (settings().simplex_strategy()) { + case simplex_strategy_enum::tableau_rows: + prepare_costs_for_r_solver(term); + settings().simplex_strategy() = simplex_strategy_enum::tableau_costs; + { + bool ret = maximize_term_on_tableau(term, term_max); + settings().simplex_strategy() = simplex_strategy_enum::tableau_rows; + set_costs_to_zero(term); + m_mpq_lar_core_solver.m_r_solver.set_status(OPTIMAL); + return ret; + } + case simplex_strategy_enum::tableau_costs: + prepare_costs_for_r_solver(term); + { + bool ret = maximize_term_on_tableau(term, term_max); + set_costs_to_zero(term); + m_mpq_lar_core_solver.m_r_solver.set_status(OPTIMAL); + return ret; + } + + case simplex_strategy_enum::lu: + lean_assert(false); // not implemented + return false; + default: + lean_unreachable(); // wrong mode + } + return false; +} +// starting from a given feasible state look for the maximum of the term +// return true if found and false if unbounded +bool lar_solver::maximize_term(const vector> & term, + impq &term_max) { + lean_assert(m_mpq_lar_core_solver.m_r_solver.current_x_is_feasible()); + m_mpq_lar_core_solver.m_r_solver.m_look_for_feasible_solution_only = false; + return maximize_term_on_corrected_r_solver(term, term_max); +} + + + +const lar_term & lar_solver::get_term(unsigned j) const { + lean_assert(j >= m_terms_start_index); + return *m_terms[j - m_terms_start_index]; +} + +void lar_solver::pop_core_solver_params() { + pop_core_solver_params(1); +} + +void lar_solver::pop_core_solver_params(unsigned k) { + A_r().pop(k); + A_d().pop(k); +} + + +void lar_solver::set_upper_bound_witness(var_index j, constraint_index ci) { + ul_pair ul = m_vars_to_ul_pairs[j]; + ul.upper_bound_witness() = ci; + m_vars_to_ul_pairs[j] = ul; +} + +void lar_solver::set_low_bound_witness(var_index j, constraint_index ci) { + ul_pair ul = m_vars_to_ul_pairs[j]; + ul.low_bound_witness() = ci; + m_vars_to_ul_pairs[j] = ul; +} + +void lar_solver::register_one_coeff_in_map(std::unordered_map & coeffs, const mpq & a, unsigned j) { + auto it = coeffs.find(j); + if (it == coeffs.end()) { + coeffs[j] = a; + } else { + it->second += a; + } +} + + +void lar_solver::substitute_terms_in_linear_expression(const vector>& left_side_with_terms, + vector> &left_side, mpq & right_side) const { + std::unordered_map coeffs; + for (auto & t : left_side_with_terms) { + unsigned j = t.second; + if (!is_term(j)) { + register_one_coeff_in_map(coeffs, t.first, j); + } else { + const lar_term & term = * m_terms[adjust_term_index(t.second)]; + for (auto & p : term.coeffs()){ + register_one_coeff_in_map(coeffs, t.first * p.second , p.first); + } + right_side += t.first * term.m_v; + } + } + + for (auto & p : coeffs) + left_side.push_back(std::make_pair(p.second, p.first)); +} + + +void lar_solver::detect_rows_of_bound_change_column_for_nbasic_column(unsigned j) { + if (A_r().row_count() != m_column_buffer.data_size()) + m_column_buffer.resize(A_r().row_count()); + else + m_column_buffer.clear(); + lean_assert(m_column_buffer.size() == 0 && m_column_buffer.is_OK()); + + m_mpq_lar_core_solver.m_r_solver.solve_Bd(j, m_column_buffer); + for (unsigned i : m_column_buffer.m_index) + m_rows_with_changed_bounds.insert(i); +} + + + +void lar_solver::detect_rows_of_bound_change_column_for_nbasic_column_tableau(unsigned j) { + for (auto & rc : m_mpq_lar_core_solver.m_r_A.m_columns[j]) + m_rows_with_changed_bounds.insert(rc.m_i); +} + +bool lar_solver::use_tableau() const { return m_settings.use_tableau(); } + +bool lar_solver::use_tableau_costs() const { + return m_settings.simplex_strategy() == simplex_strategy_enum::tableau_costs; +} + +void lar_solver::detect_rows_of_column_with_bound_change(unsigned j) { + if (m_mpq_lar_core_solver.m_r_heading[j] >= 0) { // it is a basic column + // just mark the row at touched and exit + m_rows_with_changed_bounds.insert(m_mpq_lar_core_solver.m_r_heading[j]); + return; + } + + if (use_tableau()) + detect_rows_of_bound_change_column_for_nbasic_column_tableau(j); + else + detect_rows_of_bound_change_column_for_nbasic_column(j); +} + +void lar_solver::adjust_x_of_column(unsigned j) { + lean_assert(false); +} + +bool lar_solver::row_is_correct(unsigned i) const { + numeric_pair r = zero_of_type>(); + for (const auto & c : A_r().m_rows[i]) + r += c.m_value * m_mpq_lar_core_solver.m_r_x[c.m_j]; + return is_zero(r); +} + +bool lar_solver::ax_is_correct() const { + for (unsigned i = 0; i < A_r().row_count(); i++) { + if (!row_is_correct(i)) + return false; + } + return true; +} + +bool lar_solver::tableau_with_costs() const { + return m_settings.simplex_strategy() == simplex_strategy_enum::tableau_costs; +} + +bool lar_solver::costs_are_used() const { + return m_settings.simplex_strategy() != simplex_strategy_enum::tableau_rows; +} + +void lar_solver::change_basic_x_by_delta_on_column(unsigned j, const numeric_pair & delta) { + if (use_tableau()) { + for (const auto & c : A_r().m_columns[j]) { + unsigned bj = m_mpq_lar_core_solver.m_r_basis[c.m_i]; + m_mpq_lar_core_solver.m_r_x[bj] -= A_r().get_val(c) * delta; + if (tableau_with_costs()) { + m_basic_columns_with_changed_cost.insert(bj); + } + m_mpq_lar_core_solver.m_r_solver.update_column_in_inf_set(bj); + } + } else { + m_column_buffer.clear(); + m_column_buffer.resize(A_r().row_count()); + m_mpq_lar_core_solver.m_r_solver.solve_Bd(j, m_column_buffer); + for (unsigned i : m_column_buffer.m_index) { + unsigned bj = m_mpq_lar_core_solver.m_r_basis[i]; + m_mpq_lar_core_solver.m_r_x[bj] -= m_column_buffer[i] * delta; + m_mpq_lar_core_solver.m_r_solver.update_column_in_inf_set(bj); + } + } +} + +void lar_solver::update_x_and_inf_costs_for_column_with_changed_bounds(unsigned j) { + if (m_mpq_lar_core_solver.m_r_heading[j] >= 0) { + if (costs_are_used()) { + bool was_infeas = m_mpq_lar_core_solver.m_r_solver.m_inf_set.contains(j); + m_mpq_lar_core_solver.m_r_solver.update_column_in_inf_set(j); + if (was_infeas != m_mpq_lar_core_solver.m_r_solver.m_inf_set.contains(j)) + m_basic_columns_with_changed_cost.insert(j); + } else { + m_mpq_lar_core_solver.m_r_solver.update_column_in_inf_set(j); + } + } else { + numeric_pair delta; + if (m_mpq_lar_core_solver.m_r_solver.make_column_feasible(j, delta)) + change_basic_x_by_delta_on_column(j, delta); + } +} + + +void lar_solver::detect_rows_with_changed_bounds_for_column(unsigned j) { + if (m_mpq_lar_core_solver.m_r_heading[j] >= 0) { + m_rows_with_changed_bounds.insert(m_mpq_lar_core_solver.m_r_heading[j]); + return; + } + + if (use_tableau()) + detect_rows_of_bound_change_column_for_nbasic_column_tableau(j); + else + detect_rows_of_bound_change_column_for_nbasic_column(j); +} + +void lar_solver::detect_rows_with_changed_bounds() { + for (auto j : m_columns_with_changed_bound.m_index) + detect_rows_with_changed_bounds_for_column(j); +} + +void lar_solver::update_x_and_inf_costs_for_columns_with_changed_bounds() { + for (auto j : m_columns_with_changed_bound.m_index) + update_x_and_inf_costs_for_column_with_changed_bounds(j); +} + +void lar_solver::update_x_and_inf_costs_for_columns_with_changed_bounds_tableau() { + lean_assert(ax_is_correct()); + for (auto j : m_columns_with_changed_bound.m_index) + update_x_and_inf_costs_for_column_with_changed_bounds(j); + + if (tableau_with_costs()) { + for (unsigned j : m_basic_columns_with_changed_cost.m_index) + m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); + lean_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); + } +} + + +void lar_solver::solve_with_core_solver() { + if (!use_tableau()) + add_last_rows_to_lu(m_mpq_lar_core_solver.m_r_solver); + if (m_mpq_lar_core_solver.need_to_presolve_with_double_solver()) { + add_last_rows_to_lu(m_mpq_lar_core_solver.m_d_solver); + } + m_mpq_lar_core_solver.prefix_r(); + if (costs_are_used()) { + m_basic_columns_with_changed_cost.clear(); + m_basic_columns_with_changed_cost.resize(m_mpq_lar_core_solver.m_r_x.size()); + } + if (use_tableau()) + update_x_and_inf_costs_for_columns_with_changed_bounds_tableau(); + else + update_x_and_inf_costs_for_columns_with_changed_bounds(); + m_mpq_lar_core_solver.solve(); + set_status(m_mpq_lar_core_solver.m_r_solver.get_status()); + lean_assert(m_status != OPTIMAL || all_constraints_hold()); +} + + +numeric_pair lar_solver::get_basic_var_value_from_row_directly(unsigned i) { + numeric_pair r = zero_of_type>(); + + unsigned bj = m_mpq_lar_core_solver.m_r_solver.m_basis[i]; + for (const auto & c: A_r().m_rows[i]) { + if (c.m_j == bj) continue; + const auto & x = m_mpq_lar_core_solver.m_r_x[c.m_j]; + if (!is_zero(x)) + r -= c.m_value * x; + } + return r; +} + +numeric_pair lar_solver::get_basic_var_value_from_row(unsigned i) { + if (settings().use_tableau()) { + return get_basic_var_value_from_row_directly(i); + } + + numeric_pair r = zero_of_type>(); + m_mpq_lar_core_solver.calculate_pivot_row(i); + for (unsigned j : m_mpq_lar_core_solver.m_r_solver.m_pivot_row.m_index) { + lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); + r -= m_mpq_lar_core_solver.m_r_solver.m_pivot_row.m_data[j] * m_mpq_lar_core_solver.m_r_x[j]; + } + return r; +} + +template +void lar_solver::add_last_rows_to_lu(lp_primal_core_solver & s) { + auto & f = s.m_factorization; + if (f != nullptr) { + auto columns_to_replace = f->get_set_of_columns_to_replace_for_add_last_rows(s.m_basis_heading); + if (f->m_refactor_counter + columns_to_replace.size() >= 200 || f->has_dense_submatrix()) { + delete f; + f = nullptr; + } else { + f->add_last_rows_to_B(s.m_basis_heading, columns_to_replace); + } + } + if (f == nullptr) { + init_factorization(f, s.m_A, s.m_basis, m_settings); + if (f->get_status() != LU_status::OK) { + delete f; + f = nullptr; + } + } + +} + +bool lar_solver::x_is_correct() const { + if (m_mpq_lar_core_solver.m_r_x.size() != A_r().column_count()) { + // std::cout << "the size is off " << m_r_solver.m_x.size() << ", " << A().column_count() << std::endl; + return false; + } + for (unsigned i = 0; i < A_r().row_count(); i++) { + numeric_pair delta = A_r().dot_product_with_row(i, m_mpq_lar_core_solver.m_r_x); + if (!delta.is_zero()) { + // std::cout << "x is off ("; + // std::cout << "m_b[" << i << "] = " << m_b[i] << " "; + // std::cout << "left side = " << A().dot_product_with_row(i, m_r_solver.m_x) << ' '; + // std::cout << "delta = " << delta << ' '; + // std::cout << "iters = " << total_iterations() << ")" << std::endl; + // std::cout << "row " << i << " is off" << std::endl; + return false; + } + } + return true;; + +} + +bool lar_solver::var_is_registered(var_index vj) const { + if (vj >= m_terms_start_index) { + if (vj - m_terms_start_index >= m_terms.size()) + return false; + } else if ( vj >= A_r().column_count()) { + return false; + } + return true; +} + +unsigned lar_solver::constraint_stack_size() const { + return m_constraint_count.stack_size(); +} + +void lar_solver::fill_last_row_of_A_r(static_matrix> & A, const lar_term * ls) { + lean_assert(A.row_count() > 0); + lean_assert(A.column_count() > 0); + unsigned last_row = A.row_count() - 1; + lean_assert(A.m_rows[last_row].size() == 0); + for (auto & t : ls->m_coeffs) { + lean_assert(!is_zero(t.second)); + var_index j = t.first; + A.set(last_row, j, - t.second); + } + unsigned basis_j = A.column_count() - 1; + A.set(last_row, basis_j, mpq(1)); +} + +template +void lar_solver::create_matrix_A(static_matrix & matr) { + lean_assert(false); // not implemented + /* + unsigned m = number_or_nontrivial_left_sides(); + unsigned n = m_vec_of_canonic_left_sides.size(); + if (matr.row_count() == m && matr.column_count() == n) + return; + matr.init_empty_matrix(m, n); + copy_from_mpq_matrix(matr); + */ +} + +template +void lar_solver::copy_from_mpq_matrix(static_matrix & matr) { + matr.m_rows.resize(A_r().row_count()); + matr.m_columns.resize(A_r().column_count()); + for (unsigned i = 0; i < matr.row_count(); i++) { + for (auto & it : A_r().m_rows[i]) { + matr.set(i, it.m_j, convert_struct::convert(it.get_val())); + } + } +} + + +bool lar_solver::try_to_set_fixed(column_info & ci) { + if (ci.upper_bound_is_set() && ci.low_bound_is_set() && ci.get_upper_bound() == ci.get_low_bound() && !ci.is_fixed()) { + ci.set_fixed_value(ci.get_upper_bound()); + return true; + } + return false; +} + +column_type lar_solver::get_column_type(const column_info & ci) { + auto ret = ci.get_column_type_no_flipping(); + if (ret == column_type::boxed) { // changing boxed to fixed because of the no span + if (ci.get_low_bound() == ci.get_upper_bound()) + ret = column_type::fixed; + } + return ret; +} + +std::string lar_solver::get_column_name(unsigned j) const { + if (j >= m_terms_start_index) + return std::string("_t") + T_to_string(j); + if (j >= m_columns_to_ext_vars_or_term_indices.size()) + return std::string("_s") + T_to_string(j); + + return std::string("v") + T_to_string(m_columns_to_ext_vars_or_term_indices[j]); +} + +bool lar_solver::all_constrained_variables_are_registered(const vector>& left_side) { + for (auto it : left_side) { + if (! var_is_registered(it.second)) + return false; + } + return true; +} + +bool lar_solver::all_constraints_hold() const { + if (m_settings.get_cancel_flag()) + return true; + std::unordered_map var_map; + get_model(var_map); + + for (unsigned i = 0; i < m_constraints.size(); i++) { + if (!constraint_holds(*m_constraints[i], var_map)) { + print_constraint(i, std::cout); + return false; + } + } + return true; +} + +bool lar_solver::constraint_holds(const lar_base_constraint & constr, std::unordered_map & var_map) const { + mpq left_side_val = get_left_side_val(constr, var_map); + switch (constr.m_kind) { + case LE: return left_side_val <= constr.m_right_side; + case LT: return left_side_val < constr.m_right_side; + case GE: return left_side_val >= constr.m_right_side; + case GT: return left_side_val > constr.m_right_side; + case EQ: return left_side_val == constr.m_right_side; + default: + lean_unreachable(); + } + return false; // it is unreachable +} + +bool lar_solver::the_relations_are_of_same_type(const vector> & evidence, lconstraint_kind & the_kind_of_sum) const { + unsigned n_of_G = 0, n_of_L = 0; + bool strict = false; + for (auto & it : evidence) { + mpq coeff = it.first; + constraint_index con_ind = it.second; + lconstraint_kind kind = coeff.is_pos() ? + m_constraints[con_ind]->m_kind : + flip_kind(m_constraints[con_ind]->m_kind); + if (kind == GT || kind == LT) + strict = true; + if (kind == GE || kind == GT) n_of_G++; + else if (kind == LE || kind == LT) n_of_L++; + } + the_kind_of_sum = n_of_G ? GE : (n_of_L ? LE : EQ); + if (strict) + the_kind_of_sum = static_cast((static_cast(the_kind_of_sum) / 2)); + + return n_of_G == 0 || n_of_L == 0; +} + +void lar_solver::register_in_map(std::unordered_map & coeffs, const lar_base_constraint & cn, const mpq & a) { + for (auto & it : cn.get_left_side_coefficients()) { + unsigned j = it.second; + auto p = coeffs.find(j); + if (p == coeffs.end()) + coeffs[j] = it.first * a; + else { + p->second += it.first * a; + if (p->second.is_zero()) + coeffs.erase(p); + } + } +} + +bool lar_solver::the_left_sides_sum_to_zero(const vector> & evidence) const { + std::unordered_map coeff_map; + for (auto & it : evidence) { + mpq coeff = it.first; + constraint_index con_ind = it.second; + lean_assert(con_ind < m_constraints.size()); + register_in_map(coeff_map, *m_constraints[con_ind], coeff); + } + + if (!coeff_map.empty()) { + std::cout << "left side = "; + vector> t; + for (auto & it : coeff_map) { + t.push_back(std::make_pair(it.second, it.first)); + } + print_linear_combination_of_column_indices(t, std::cout); + std::cout << std::endl; + return false; + } + + return true; +} + +bool lar_solver::the_right_sides_do_not_sum_to_zero(const vector> & evidence) { + mpq ret = numeric_traits::zero(); + for (auto & it : evidence) { + mpq coeff = it.first; + constraint_index con_ind = it.second; + lean_assert(con_ind < m_constraints.size()); + const lar_constraint & constr = *m_constraints[con_ind]; + ret += constr.m_right_side * coeff; + } + return !numeric_traits::is_zero(ret); +} + +bool lar_solver::explanation_is_correct(const vector>& explanation) const { +#ifdef LEAN_DEBUG + lconstraint_kind kind; + lean_assert(the_relations_are_of_same_type(explanation, kind)); + lean_assert(the_left_sides_sum_to_zero(explanation)); + mpq rs = sum_of_right_sides_of_explanation(explanation); + switch (kind) { + case LE: lean_assert(rs < zero_of_type()); + break; + case LT: lean_assert(rs <= zero_of_type()); + break; + case GE: lean_assert(rs > zero_of_type()); + break; + case GT: lean_assert(rs >= zero_of_type()); + break; + case EQ: lean_assert(rs != zero_of_type()); + break; + default: + lean_assert(false); + return false; + } +#endif + return true; +} + +bool lar_solver::inf_explanation_is_correct() const { +#ifdef LEAN_DEBUG + vector> explanation; + get_infeasibility_explanation(explanation); + return explanation_is_correct(explanation); +#endif + return true; +} + +mpq lar_solver::sum_of_right_sides_of_explanation(const vector> & explanation) const { + mpq ret = numeric_traits::zero(); + for (auto & it : explanation) { + mpq coeff = it.first; + constraint_index con_ind = it.second; + lean_assert(con_ind < m_constraints.size()); + ret += (m_constraints[con_ind]->m_right_side - m_constraints[con_ind]->get_free_coeff_of_left_side()) * coeff; + } + return ret; +} + +bool lar_solver::has_lower_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) { + + if (var >= m_vars_to_ul_pairs.size()) { + // TBD: bounds on terms could also be used, caller may have to track these. + return false; + } + const ul_pair & ul = m_vars_to_ul_pairs[var]; + ci = ul.low_bound_witness(); + if (ci != static_cast(-1)) { + auto& p = m_mpq_lar_core_solver.m_r_low_bounds()[var]; + value = p.x; + is_strict = p.y.is_pos(); + return true; + } + else { + return false; + } +} + +bool lar_solver::has_upper_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) { + + if (var >= m_vars_to_ul_pairs.size()) { + // TBD: bounds on terms could also be used, caller may have to track these. + return false; + } + const ul_pair & ul = m_vars_to_ul_pairs[var]; + ci = ul.upper_bound_witness(); + if (ci != static_cast(-1)) { + auto& p = m_mpq_lar_core_solver.m_r_upper_bounds()[var]; + value = p.x; + is_strict = p.y.is_neg(); + return true; + } + else { + return false; + } +} + +void lar_solver::get_infeasibility_explanation(vector> & explanation) const { + explanation.clear(); + if (m_infeasible_column_index != -1) { + fill_explanation_from_infeasible_column(explanation); + return; + } + if (m_mpq_lar_core_solver.get_infeasible_sum_sign() == 0) { + return; + } + // the infeasibility sign + int inf_sign; + auto inf_row = m_mpq_lar_core_solver.get_infeasibility_info(inf_sign); + get_infeasibility_explanation_for_inf_sign(explanation, inf_row, inf_sign); + lean_assert(explanation_is_correct(explanation)); +} + + + +void lar_solver::get_infeasibility_explanation_for_inf_sign( + vector> & explanation, + const vector> & inf_row, + int inf_sign) const { + + for (auto & it : inf_row) { + mpq coeff = it.first; + unsigned j = it.second; + + int adj_sign = coeff.is_pos() ? inf_sign : -inf_sign; + const ul_pair & ul = m_vars_to_ul_pairs[j]; + + constraint_index bound_constr_i = adj_sign < 0 ? ul.upper_bound_witness() : ul.low_bound_witness(); + lean_assert(bound_constr_i < m_constraints.size()); + explanation.push_back(std::make_pair(coeff, bound_constr_i)); + } +} + +void lar_solver::get_model(std::unordered_map & variable_values) const { + mpq delta = mpq(1, 2); // start from 0.5 to have less clashes + lean_assert(m_status == OPTIMAL); + unsigned i; + do { + + // different pairs have to produce different singleton values + std::unordered_set set_of_different_pairs; + std::unordered_set set_of_different_singles; + delta = m_mpq_lar_core_solver.find_delta_for_strict_bounds(delta); + for (i = 0; i < m_mpq_lar_core_solver.m_r_x.size(); i++ ) { + const numeric_pair & rp = m_mpq_lar_core_solver.m_r_x[i]; + set_of_different_pairs.insert(rp); + mpq x = rp.x + delta * rp.y; + set_of_different_singles.insert(x); + if (set_of_different_pairs.size() + != set_of_different_singles.size()) { + delta /= mpq(2); + break; + } + + variable_values[i] = x; + } + } while (i != m_mpq_lar_core_solver.m_r_x.size()); +} + +std::string lar_solver::get_variable_name(var_index vi) const { + return get_column_name(vi); +} + +// ********** print region start +void lar_solver::print_constraint(constraint_index ci, std::ostream & out) const { + if (ci >= m_constraints.size()) { + out << "constraint " << T_to_string(ci) << " is not found"; + out << std::endl; + return; + } + + print_constraint(m_constraints[ci], out); +} + +void lar_solver::print_constraints(std::ostream& out) const { + for (auto c : m_constraints) { + print_constraint(c, out); + } +} + +void lar_solver::print_terms(std::ostream& out) const { + for (auto it : m_terms) { + print_term(*it, out); + out << "\n"; + } +} + +void lar_solver::print_left_side_of_constraint(const lar_base_constraint * c, std::ostream & out) const { + print_linear_combination_of_column_indices(c->get_left_side_coefficients(), out); + mpq free_coeff = c->get_free_coeff_of_left_side(); + if (!is_zero(free_coeff)) + out << " + " << free_coeff; + +} + +void lar_solver::print_term(lar_term const& term, std::ostream & out) const { + if (!numeric_traits::is_zero(term.m_v)) { + out << term.m_v << " + "; + } + print_linear_combination_of_column_indices(term.coeffs_as_vector(), out); +} + +mpq lar_solver::get_left_side_val(const lar_base_constraint & cns, const std::unordered_map & var_map) const { + mpq ret = cns.get_free_coeff_of_left_side(); + for (auto & it : cns.get_left_side_coefficients()) { + var_index j = it.second; + auto vi = var_map.find(j); + lean_assert(vi != var_map.end()); + ret += it.first * vi->second; + } + return ret; +} + +void lar_solver::print_constraint(const lar_base_constraint * c, std::ostream & out) const { + print_left_side_of_constraint(c, out); + out << " " << lconstraint_kind_string(c->m_kind) << " " << c->m_right_side << std::endl; +} + +void lar_solver::fill_var_set_for_random_update(unsigned sz, var_index const * vars, vector& column_list) { + for (unsigned i = 0; i < sz; i++) { + var_index var = vars[i]; + if (var >= m_terms_start_index) { // handle the term + for (auto & it : m_terms[var - m_terms_start_index]->m_coeffs) { + column_list.push_back(it.first); + } + } else { + column_list.push_back(var); + } + } +} + +void lar_solver::random_update(unsigned sz, var_index const * vars) { + vector column_list; + fill_var_set_for_random_update(sz, vars, column_list); + random_updater ru(m_mpq_lar_core_solver, column_list); + ru.update(); +} + + +void lar_solver::pivot_fixed_vars_from_basis() { + m_mpq_lar_core_solver.m_r_solver.pivot_fixed_vars_from_basis(); +} + +void lar_solver::pop() { + pop(1); +} + +bool lar_solver::column_represents_row_in_tableau(unsigned j) { + return m_vars_to_ul_pairs()[j].m_i != static_cast(-1); +} + +void lar_solver::make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsigned i, unsigned j) { + // i, j - is the indices of the bottom-right element of the tableau + lean_assert(A_r().row_count() == i + 1 && A_r().column_count() == j + 1); + auto & last_column = A_r().m_columns[j]; + int non_zero_column_cell_index = -1; + for (unsigned k = last_column.size(); k-- > 0;){ + auto & cc = last_column[k]; + if (cc.m_i == i) + return; + non_zero_column_cell_index = k; + } + + lean_assert(non_zero_column_cell_index != -1); + lean_assert(static_cast(non_zero_column_cell_index) != i); + m_mpq_lar_core_solver.m_r_solver.transpose_rows_tableau(last_column[non_zero_column_cell_index].m_i, i); +} + +void lar_solver::remove_last_row_and_column_from_tableau(unsigned j) { + lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + auto & slv = m_mpq_lar_core_solver.m_r_solver; + unsigned i = A_r().row_count() - 1; //last row index + make_sure_that_the_bottom_right_elem_not_zero_in_tableau(i, j); + if (slv.m_basis_heading[j] < 0) { + slv.pivot_column_tableau(j, i); + } + + auto & last_row = A_r().m_rows[i]; + mpq &cost_j = m_mpq_lar_core_solver.m_r_solver.m_costs[j]; + bool cost_is_nz = !is_zero(cost_j); + for (unsigned k = last_row.size(); k-- > 0;) { + auto &rc = last_row[k]; + if (cost_is_nz) { + m_mpq_lar_core_solver.m_r_solver.m_d[rc.m_j] += cost_j*rc.get_val(); + } + + A_r().remove_element(last_row, rc); + } + lean_assert(last_row.size() == 0); + lean_assert(A_r().m_columns[j].size() == 0); + A_r().m_rows.pop_back(); + A_r().m_columns.pop_back(); + slv.m_b.pop_back(); +} + +void lar_solver::remove_last_column_from_tableau(unsigned j) { + lean_assert(j == A_r().column_count() - 1); + // the last column has to be empty + lean_assert(A_r().m_columns[j].size() == 0); + A_r().m_columns.pop_back(); +} + +void lar_solver::remove_last_column_from_basis_tableau(unsigned j) { + auto& rslv = m_mpq_lar_core_solver.m_r_solver; + int i = rslv.m_basis_heading[j]; + if (i >= 0) { // j is a basic var + int last_pos = static_cast(rslv.m_basis.size()) - 1; + lean_assert(last_pos >= 0); + if (i != last_pos) { + unsigned j_at_last_pos = rslv.m_basis[last_pos]; + rslv.m_basis[i] = j_at_last_pos; + rslv.m_basis_heading[j_at_last_pos] = i; + } + rslv.m_basis.pop_back(); // remove j from the basis + } else { + int last_pos = static_cast(rslv.m_nbasis.size()) - 1; + lean_assert(last_pos >= 0); + i = - 1 - i; + if (i != last_pos) { + unsigned j_at_last_pos = rslv.m_nbasis[last_pos]; + rslv.m_nbasis[i] = j_at_last_pos; + rslv.m_basis_heading[j_at_last_pos] = - i - 1; + } + rslv.m_nbasis.pop_back(); // remove j from the basis + } + rslv.m_basis_heading.pop_back(); + lean_assert(rslv.m_basis.size() == A_r().row_count()); + lean_assert(rslv.basis_heading_is_correct()); +} + +void lar_solver::remove_column_from_tableau(unsigned j) { + auto& rslv = m_mpq_lar_core_solver.m_r_solver; + lean_assert(j == A_r().column_count() - 1); + lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + if (column_represents_row_in_tableau(j)) { + remove_last_row_and_column_from_tableau(j); + if (rslv.m_basis_heading[j] < 0) + rslv.change_basis_unconditionally(j, rslv.m_basis[A_r().row_count()]); // A_r().row_count() is the index of the last row in the basis still + } + else { + remove_last_column_from_tableau(j); + } + rslv.m_x.pop_back(); + rslv.m_d.pop_back(); + rslv.m_costs.pop_back(); + + remove_last_column_from_basis_tableau(j); + lean_assert(m_mpq_lar_core_solver.r_basis_is_OK()); + lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); +} + +void lar_solver::pop_tableau() { + lean_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); + + lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); + lean_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); + // We remove last variables starting from m_column_names.size() to m_vec_of_canonic_left_sides.size(). + // At this moment m_column_names is already popped + for (unsigned j = A_r().column_count(); j-- > m_columns_to_ext_vars_or_term_indices.size();) + remove_column_from_tableau(j); + lean_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); + lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); + lean_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); +} + +void lar_solver::clean_inf_set_of_r_solver_after_pop() { + vector became_feas; + clean_large_elements_after_pop(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.m_inf_set); + std::unordered_set basic_columns_with_changed_cost; + auto inf_index_copy = m_mpq_lar_core_solver.m_r_solver.m_inf_set.m_index; + for (auto j: inf_index_copy) { + if (m_mpq_lar_core_solver.m_r_heading[j] >= 0) { + continue; + } + // some basic columns might become non-basic - these columns need to be made feasible + numeric_pair delta; + if (m_mpq_lar_core_solver.m_r_solver.make_column_feasible(j, delta)) + change_basic_x_by_delta_on_column(j, delta); + became_feas.push_back(j); + } + + for (unsigned j : became_feas) { + lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); + m_mpq_lar_core_solver.m_r_solver.m_d[j] -= m_mpq_lar_core_solver.m_r_solver.m_costs[j]; + m_mpq_lar_core_solver.m_r_solver.m_costs[j] = zero_of_type(); + m_mpq_lar_core_solver.m_r_solver.m_inf_set.erase(j); + } + became_feas.clear(); + for (unsigned j : m_mpq_lar_core_solver.m_r_solver.m_inf_set.m_index) { + lean_assert(m_mpq_lar_core_solver.m_r_heading[j] >= 0); + if (m_mpq_lar_core_solver.m_r_solver.column_is_feasible(j)) + became_feas.push_back(j); + } + for (unsigned j : became_feas) + m_mpq_lar_core_solver.m_r_solver.m_inf_set.erase(j); + + + if (use_tableau_costs()) { + for (unsigned j : became_feas) + m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); + for (unsigned j : basic_columns_with_changed_cost) + m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); + lean_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); + } +} + +void lar_solver::shrink_explanation_to_minimum(vector> & explanation) const { + // implementing quickXplain + quick_xplain::run(explanation, *this); + lean_assert(this->explanation_is_correct(explanation)); +} + +bool lar_solver::model_is_int_feasible() const { + unsigned n = A_r().column_count(); + for (unsigned j = 0; j < n; j++) { + if (column_is_int(j) && !column_value_is_integer(j)) + return false; + } + return true; +} + +bool lar_solver::term_is_int(const lar_term * t) const { + for (auto const & p : t->m_coeffs) + if (!column_is_int(p.first) || p.second.is_int()) + return false; + return t->m_v.is_int(); +} + +bool lar_solver::var_is_int(var_index v) const { + if (is_term(v)) { + lar_term const& t = get_term(v); + return term_is_int(&t); + } + else { + return column_is_int(v); + } +} + +bool lar_solver::column_is_int(unsigned j) const { + unsigned ext_var = m_columns_to_ext_vars_or_term_indices[j]; + lean_assert(contains(m_ext_vars_to_columns, ext_var)); + return m_ext_vars_to_columns.find(ext_var)->second.is_integer(); +} + +bool lar_solver::column_is_fixed(unsigned j) const { + return m_mpq_lar_core_solver.column_is_fixed(j); +} + + +bool lar_solver::ext_var_is_int(var_index ext_var) const { + auto it = m_ext_vars_to_columns.find(ext_var); + lean_assert(it != m_ext_vars_to_columns.end()); + return it == m_ext_vars_to_columns.end() || it->second.is_integer(); +} + + // below is the initialization functionality of lar_solver + +bool lar_solver::strategy_is_undecided() const { + return m_settings.simplex_strategy() == simplex_strategy_enum::undecided; +} + +var_index lar_solver::add_var(unsigned ext_j, bool is_int) { + TRACE("add_var", tout << "adding var " << ext_j << (is_int? " int" : " nonint") << std::endl;); + var_index i; + lean_assert(ext_j < m_terms_start_index); + + if (ext_j >= m_terms_start_index) + throw 0; // todo : what is the right way to exit? + auto it = m_ext_vars_to_columns.find(ext_j); + if (it != m_ext_vars_to_columns.end()) { + return it->second.ext_j(); + } + lean_assert(m_vars_to_ul_pairs.size() == A_r().column_count()); + i = A_r().column_count(); + m_vars_to_ul_pairs.push_back(ul_pair(static_cast(-1))); + add_non_basic_var_to_core_fields(ext_j, is_int); + lean_assert(sizes_are_correct()); + return i; +} + +void lar_solver::register_new_ext_var_index(unsigned ext_v, bool is_int) { + lean_assert(!contains(m_ext_vars_to_columns, ext_v)); + unsigned j = static_cast(m_ext_vars_to_columns.size()); + m_ext_vars_to_columns.insert(std::make_pair(ext_v, ext_var_info(j, is_int))); + lean_assert(m_columns_to_ext_vars_or_term_indices.size() == j); + m_columns_to_ext_vars_or_term_indices.push_back(ext_v); +} + +void lar_solver::add_non_basic_var_to_core_fields(unsigned ext_j, bool is_int) { + register_new_ext_var_index(ext_j, is_int); + m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column); + m_columns_with_changed_bound.increase_size_by_one(); + add_new_var_to_core_fields_for_mpq(false); + if (use_lu()) + add_new_var_to_core_fields_for_doubles(false); +} + +void lar_solver::add_new_var_to_core_fields_for_doubles(bool register_in_basis) { + unsigned j = A_d().column_count(); + A_d().add_column(); + lean_assert(m_mpq_lar_core_solver.m_d_x.size() == j); + // lean_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 + 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_upper_bounds.resize(j + 1); + lean_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) { + A_d().add_row(); + m_mpq_lar_core_solver.m_d_heading.push_back(m_mpq_lar_core_solver.m_d_basis.size()); + m_mpq_lar_core_solver.m_d_basis.push_back(j); + } + else { + m_mpq_lar_core_solver.m_d_heading.push_back(-static_cast(m_mpq_lar_core_solver.m_d_nbasis.size()) - 1); + m_mpq_lar_core_solver.m_d_nbasis.push_back(j); + } +} + +void lar_solver::add_new_var_to_core_fields_for_mpq(bool register_in_basis) { + unsigned j = A_r().column_count(); + A_r().add_column(); + lean_assert(m_mpq_lar_core_solver.m_r_x.size() == j); + // lean_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 + 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_upper_bounds.increase_size_by_one(); + m_mpq_lar_core_solver.m_r_solver.m_inf_set.increase_size_by_one(); + m_mpq_lar_core_solver.m_r_solver.m_costs.resize(j + 1); + m_mpq_lar_core_solver.m_r_solver.m_d.resize(j + 1); + lean_assert(m_mpq_lar_core_solver.m_r_heading.size() == j); // as A().column_count() on the entry to the method + if (register_in_basis) { + A_r().add_row(); + m_mpq_lar_core_solver.m_r_heading.push_back(m_mpq_lar_core_solver.m_r_basis.size()); + m_mpq_lar_core_solver.m_r_basis.push_back(j); + if (m_settings.bound_propagation()) + m_rows_with_changed_bounds.insert(A_r().row_count() - 1); + } + else { + m_mpq_lar_core_solver.m_r_heading.push_back(-static_cast(m_mpq_lar_core_solver.m_r_nbasis.size()) - 1); + m_mpq_lar_core_solver.m_r_nbasis.push_back(j); + } +} + + +var_index lar_solver::add_term_undecided(const vector> & coeffs, + const mpq &m_v) { + m_terms.push_back(new lar_term(coeffs, m_v)); + return m_terms_start_index + m_terms.size() - 1; +} + +// terms +var_index lar_solver::add_term(const vector> & coeffs, + const mpq &m_v) { + if (strategy_is_undecided()) + return add_term_undecided(coeffs, m_v); + + m_terms.push_back(new lar_term(coeffs, m_v)); + unsigned adjusted_term_index = m_terms.size() - 1; + var_index ret = m_terms_start_index + adjusted_term_index; + if (use_tableau() && !coeffs.empty()) { + add_row_for_term(m_terms.back(), ret); + if (m_settings.bound_propagation()) + m_rows_with_changed_bounds.insert(A_r().row_count() - 1); + } + lean_assert(m_ext_vars_to_columns.size() == A_r().column_count()); + return ret; +} + +void lar_solver::add_row_for_term(const lar_term * term, unsigned term_ext_index) { + lean_assert(sizes_are_correct()); + add_row_from_term_no_constraint(term, term_ext_index); + lean_assert(sizes_are_correct()); +} + +void lar_solver::add_row_from_term_no_constraint(const lar_term * term, unsigned term_ext_index) { + register_new_ext_var_index(term_ext_index, term_is_int(term)); + // j will be a new variable + unsigned j = A_r().column_count(); + ul_pair ul(j); + m_vars_to_ul_pairs.push_back(ul); + add_basic_var_to_core_fields(); + if (use_tableau()) { + auto it = iterator_on_term_with_basis_var(*term, j); + A_r().fill_last_row_with_pivoting(it, + m_mpq_lar_core_solver.m_r_solver.m_basis_heading); + m_mpq_lar_core_solver.m_r_solver.m_b.resize(A_r().column_count(), zero_of_type()); + } + else { + fill_last_row_of_A_r(A_r(), term); + } + m_mpq_lar_core_solver.m_r_x[j] = get_basic_var_value_from_row_directly(A_r().row_count() - 1); + if (use_lu()) + fill_last_row_of_A_d(A_d(), term); +} + +void lar_solver::add_basic_var_to_core_fields() { + bool use_lu = m_mpq_lar_core_solver.need_to_presolve_with_double_solver(); + lean_assert(!use_lu || A_r().column_count() == A_d().column_count()); + m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column); + m_columns_with_changed_bound.increase_size_by_one(); + m_rows_with_changed_bounds.increase_size_by_one(); + add_new_var_to_core_fields_for_mpq(true); + if (use_lu) + add_new_var_to_core_fields_for_doubles(true); +} + +bool lar_solver::bound_is_integer_if_needed(unsigned j, const mpq & right_side) const { + if (!column_is_int(j)) + return true; + return right_side.is_int(); +} + +constraint_index lar_solver::add_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side) { + constraint_index ci = m_constraints.size(); + if (!is_term(j)) { // j is a var + lean_assert(bound_is_integer_if_needed(j, right_side)); + auto vc = new lar_var_constraint(j, kind, right_side); + m_constraints.push_back(vc); + update_column_type_and_bound(j, kind, right_side, ci); + } + else { + add_var_bound_on_constraint_for_term(j, kind, right_side, ci); + } + lean_assert(sizes_are_correct()); + return ci; +} + +void lar_solver::update_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index) { + switch (m_mpq_lar_core_solver.m_column_types[j]) { + case column_type::free_column: + update_free_column_type_and_bound(j, kind, right_side, constr_index); + break; + case column_type::boxed: + update_boxed_column_type_and_bound(j, kind, right_side, constr_index); + break; + case column_type::low_bound: + update_low_bound_column_type_and_bound(j, kind, right_side, constr_index); + break; + case column_type::upper_bound: + update_upper_bound_column_type_and_bound(j, kind, right_side, constr_index); + break; + case column_type::fixed: + update_fixed_column_type_and_bound(j, kind, right_side, constr_index); + break; + default: + lean_assert(false); // cannot be here + } +} + +void lar_solver::add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { + lean_assert(is_term(j)); + unsigned adjusted_term_index = adjust_term_index(j); + lean_assert(!term_is_int(m_terms[adjusted_term_index]) || right_side.is_int()); + auto it = m_ext_vars_to_columns.find(j); + if (it != m_ext_vars_to_columns.end()) { + unsigned term_j = it->second.ext_j(); + 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)); + update_column_type_and_bound(term_j, kind, rs, ci); + } + else { + add_constraint_from_term_and_create_new_column_row(j, m_terms[adjusted_term_index], kind, right_side); + } +} + +constraint_index lar_solver::add_constraint(const vector>& left_side_with_terms, lconstraint_kind kind_par, const mpq& right_side_parm) { + vector> left_side; + mpq rs = -right_side_parm; + substitute_terms_in_linear_expression(left_side_with_terms, left_side, rs); + unsigned term_index = add_term(left_side, zero_of_type()); + constraint_index ci = m_constraints.size(); + add_var_bound_on_constraint_for_term(term_index, kind_par, -rs, ci); + return ci; +} + +void lar_solver::add_constraint_from_term_and_create_new_column_row(unsigned term_j, const lar_term* term, + lconstraint_kind kind, const mpq & right_side) { + + add_row_from_term_no_constraint(term, term_j); + unsigned j = A_r().column_count() - 1; + update_column_type_and_bound(j, kind, right_side - term->m_v, m_constraints.size()); + m_constraints.push_back(new lar_term_constraint(term, kind, right_side)); + lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); +} + +void lar_solver::decide_on_strategy_and_adjust_initial_state() { + lean_assert(strategy_is_undecided()); + if (m_vars_to_ul_pairs.size() > m_settings.column_number_threshold_for_using_lu_in_lar_solver) { + m_settings.simplex_strategy() = simplex_strategy_enum::lu; + } + else { + m_settings.simplex_strategy() = simplex_strategy_enum::tableau_rows; // todo: when to switch to tableau_costs? + } + adjust_initial_state(); +} + +void lar_solver::adjust_initial_state() { + switch (m_settings.simplex_strategy()) { + case simplex_strategy_enum::lu: + adjust_initial_state_for_lu(); + break; + case simplex_strategy_enum::tableau_rows: + adjust_initial_state_for_tableau_rows(); + break; + case simplex_strategy_enum::tableau_costs: + lean_assert(false); // not implemented + case simplex_strategy_enum::undecided: + adjust_initial_state_for_tableau_rows(); + break; + } +} + +void lar_solver::adjust_initial_state_for_lu() { + copy_from_mpq_matrix(A_d()); + unsigned n = A_d().column_count(); + m_mpq_lar_core_solver.m_d_x.resize(n); + m_mpq_lar_core_solver.m_d_low_bounds.resize(n); + m_mpq_lar_core_solver.m_d_upper_bounds.resize(n); + m_mpq_lar_core_solver.m_d_heading = m_mpq_lar_core_solver.m_r_heading; + m_mpq_lar_core_solver.m_d_basis = m_mpq_lar_core_solver.m_r_basis; + + /* + unsigned j = A_d().column_count(); + A_d().add_column(); + lean_assert(m_mpq_lar_core_solver.m_d_x.size() == j); + // lean_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 + 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_upper_bounds.resize(j + 1); + lean_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) { + A_d().add_row(); + m_mpq_lar_core_solver.m_d_heading.push_back(m_mpq_lar_core_solver.m_d_basis.size()); + m_mpq_lar_core_solver.m_d_basis.push_back(j); + }else { + m_mpq_lar_core_solver.m_d_heading.push_back(- static_cast(m_mpq_lar_core_solver.m_d_nbasis.size()) - 1); + m_mpq_lar_core_solver.m_d_nbasis.push_back(j); + }*/ +} + +void lar_solver::adjust_initial_state_for_tableau_rows() { + for (unsigned j = 0; j < m_terms.size(); j++) { + if (contains(m_ext_vars_to_columns, j + m_terms_start_index)) + continue; + add_row_from_term_no_constraint(m_terms[j], j + m_terms_start_index); + } +} + +// this fills the last row of A_d and sets the basis column: -1 in the last column of the row +void lar_solver::fill_last_row_of_A_d(static_matrix & A, const lar_term* ls) { + lean_assert(A.row_count() > 0); + lean_assert(A.column_count() > 0); + unsigned last_row = A.row_count() - 1; + lean_assert(A.m_rows[last_row].empty()); + + for (auto & t : ls->m_coeffs) { + lean_assert(!is_zero(t.second)); + var_index j = t.first; + A.set(last_row, j, -t.second.get_double()); + } + + unsigned basis_j = A.column_count() - 1; + A.set(last_row, basis_j, -1); +} + +void lar_solver::update_free_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_ind) { + mpq y_of_bound(0); + switch (kind) { + case LT: + y_of_bound = -1; + case LE: + m_mpq_lar_core_solver.m_column_types[j] = column_type::upper_bound; + lean_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound); + lean_assert(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j); + { + auto up = numeric_pair(right_side, y_of_bound); + m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; + } + set_upper_bound_witness(j, constr_ind); + break; + case GT: + y_of_bound = 1; + case GE: + m_mpq_lar_core_solver.m_column_types[j] = column_type::low_bound; + lean_assert(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j); + { + auto low = numeric_pair(right_side, y_of_bound); + m_mpq_lar_core_solver.m_r_low_bounds[j] = low; + } + set_low_bound_witness(j, constr_ind); + break; + case EQ: + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = numeric_pair(right_side, zero_of_type()); + set_upper_bound_witness(j, constr_ind); + set_low_bound_witness(j, constr_ind); + break; + + default: + lean_unreachable(); + + } + m_columns_with_changed_bound.insert(j); +} + +void lar_solver::update_upper_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { + lean_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound); + mpq y_of_bound(0); + switch (kind) { + case LT: + y_of_bound = -1; + case LE: + { + auto up = numeric_pair(right_side, y_of_bound); + if (up < m_mpq_lar_core_solver.m_r_upper_bounds()[j]) { + m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; + set_upper_bound_witness(j, ci); + m_columns_with_changed_bound.insert(j); + } + } + break; + case GT: + y_of_bound = 1; + case GE: + m_mpq_lar_core_solver.m_column_types[j] = column_type::boxed; + { + auto low = numeric_pair(right_side, y_of_bound); + m_mpq_lar_core_solver.m_r_low_bounds[j] = low; + set_low_bound_witness(j, ci); + m_columns_with_changed_bound.insert(j); + if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + } + else { + m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j] ? column_type::boxed : column_type::fixed; + } + } + break; + case EQ: + { + auto v = numeric_pair(right_side, zero_of_type()); + if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = INFEASIBLE; + set_low_bound_witness(j, ci); + m_infeasible_column_index = j; + } + else { + m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; + m_columns_with_changed_bound.insert(j); + set_low_bound_witness(j, ci); + set_upper_bound_witness(j, ci); + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + } + break; + } + break; + + default: + lean_unreachable(); + + } +} + +void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { + lean_assert(m_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])); + mpq y_of_bound(0); + switch (kind) { + case LT: + y_of_bound = -1; + case LE: + { + auto up = numeric_pair(right_side, y_of_bound); + if (up < m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; + set_upper_bound_witness(j, ci); + m_columns_with_changed_bound.insert(j); + } + + if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = INFEASIBLE; + lean_assert(false); + m_infeasible_column_index = j; + } + else { + if (m_mpq_lar_core_solver.m_r_low_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j]) + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + } + } + break; + case GT: + y_of_bound = 1; + case GE: + { + auto low = numeric_pair(right_side, y_of_bound); + if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_mpq_lar_core_solver.m_r_low_bounds[j] = low; + m_columns_with_changed_bound.insert(j); + set_low_bound_witness(j, ci); + } + if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + } + else if (low == m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + } + } + break; + case EQ: + { + auto v = numeric_pair(right_side, zero_of_type()); + if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + set_upper_bound_witness(j, ci); + } + else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + set_low_bound_witness(j, ci); + } + else { + m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; + set_low_bound_witness(j, ci); + set_upper_bound_witness(j, ci); + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + m_columns_with_changed_bound.insert(j); + } + + break; + } + + default: + lean_unreachable(); + + } +} +void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { + lean_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::low_bound); + mpq y_of_bound(0); + switch (kind) { + case LT: + y_of_bound = -1; + case LE: + { + auto up = numeric_pair(right_side, y_of_bound); + m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; + set_upper_bound_witness(j, ci); + m_columns_with_changed_bound.insert(j); + + if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + } + else { + m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j] ? column_type::boxed : column_type::fixed; + } + } + break; + case GT: + y_of_bound = 1; + case GE: + { + auto low = numeric_pair(right_side, y_of_bound); + if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_mpq_lar_core_solver.m_r_low_bounds[j] = low; + m_columns_with_changed_bound.insert(j); + set_low_bound_witness(j, ci); + } + } + break; + case EQ: + { + auto v = numeric_pair(right_side, zero_of_type()); + if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + set_upper_bound_witness(j, ci); + } + else { + m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v; + set_low_bound_witness(j, ci); + set_upper_bound_witness(j, ci); + m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; + } + m_columns_with_changed_bound.insert(j); + break; + } + + default: + lean_unreachable(); + + } +} + +void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { + lean_assert(m_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])); + lean_assert(m_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())); + auto v = numeric_pair(right_side, mpq(0)); + + mpq y_of_bound(0); + switch (kind) { + case LT: + if (v <= m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + set_upper_bound_witness(j, ci); + } + break; + case LE: + { + if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + set_upper_bound_witness(j, ci); + } + } + break; + case GT: + { + if (v >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + set_low_bound_witness(j, ci); + } + } + break; + case GE: + { + if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + set_low_bound_witness(j, ci); + } + } + break; + case EQ: + { + if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + set_upper_bound_witness(j, ci); + } + else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { + m_status = INFEASIBLE; + m_infeasible_column_index = j; + set_low_bound_witness(j, ci); + } + break; + } + + default: + lean_unreachable(); + + } +} + + +} // namespace lean + + diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index b74515566..dbccbc9cf 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -30,1520 +30,421 @@ #include "util/lp/iterator_on_row.h" #include "util/lp/quick_xplain.h" #include "util/lp/conversion_helper.h" +#include "util/lp/int_solver.h" +#include "util/lp/nra_solver.h" + namespace lean { + class lar_solver : public column_namer { + class ext_var_info { + unsigned m_ext_j; // the external index + bool m_is_integer; + public: + ext_var_info(unsigned j): ext_var_info(j, false) {} + ext_var_info(unsigned j , bool is_int) : m_ext_j(j), m_is_integer(is_int) {} + unsigned ext_j() const { return m_ext_j;} + bool is_integer() const {return m_is_integer;} + }; //////////////////// fields ////////////////////////// - lp_settings m_settings; - stacked_value m_status; - stacked_value m_simplex_strategy; - std::unordered_map m_ext_vars_to_columns; - vector m_columns_to_ext_vars_or_term_indices; - stacked_vector m_vars_to_ul_pairs; - vector m_constraints; - stacked_value m_constraint_count; + lp_settings m_settings; + stacked_value m_status; + stacked_value m_simplex_strategy; + std::unordered_map m_ext_vars_to_columns; + vector m_columns_to_ext_vars_or_term_indices; + stacked_vector m_vars_to_ul_pairs; + vector m_constraints; + stacked_value m_constraint_count; // the set of column indices j such that bounds have changed for j - int_set m_columns_with_changed_bound; - int_set m_rows_with_changed_bounds; - int_set m_basic_columns_with_changed_cost; - stacked_value m_infeasible_column_index; // such can be found at the initialization step - stacked_value m_term_count; - vector m_terms; - vector m_orig_terms; - const var_index m_terms_start_index; - indexed_vector m_column_buffer; + int_set m_columns_with_changed_bound; + int_set m_rows_with_changed_bounds; + int_set m_basic_columns_with_changed_cost; + stacked_value m_infeasible_column_index; // such can be found at the initialization step + stacked_value m_term_count; + vector m_terms; + const var_index m_terms_start_index; + indexed_vector m_column_buffer; public: lar_core_solver m_mpq_lar_core_solver; - unsigned constraint_count() const { - return m_constraints.size(); - } - const lar_base_constraint& get_constraint(unsigned ci) const { - return *(m_constraints[ci]); - } + unsigned constraint_count() const; + const lar_base_constraint& get_constraint(unsigned ci) const; ////////////////// methods //////////////////////////////// - static_matrix> & A_r() { return m_mpq_lar_core_solver.m_r_A;} - static_matrix> const & A_r() const { return m_mpq_lar_core_solver.m_r_A;} - static_matrix & A_d() { return m_mpq_lar_core_solver.m_d_A;} - static_matrix const & A_d() const { return m_mpq_lar_core_solver.m_d_A;} + static_matrix> & A_r(); + static_matrix> const & A_r() const; + static_matrix & A_d(); + static_matrix const & A_d() const; static bool valid_index(unsigned j){ return static_cast(j) >= 0;} - + bool column_is_int(unsigned j) const; + bool column_is_fixed(unsigned j) const; public: - lp_settings & settings() { return m_settings;} - lp_settings const & settings() const { return m_settings;} + // init region + bool strategy_is_undecided() const; - void clear() {lean_assert(false); // not implemented - } + var_index add_var(unsigned ext_j, bool is_integer); + void register_new_ext_var_index(unsigned ext_v, bool is_int); - lar_solver() : m_status(OPTIMAL), - m_infeasible_column_index(-1), - m_terms_start_index(1000000), - m_mpq_lar_core_solver(m_settings, *this) - {} + bool term_is_int(const lar_term * t) const; + + bool var_is_int(var_index v) const; + + bool ext_var_is_int(var_index ext_var) const; - void set_propagate_bounds_on_pivoted_rows_mode(bool v) { - m_mpq_lar_core_solver.m_r_solver.m_pivoted_rows = v? (& m_rows_with_changed_bounds) : nullptr; - } + void add_non_basic_var_to_core_fields(unsigned ext_j, bool is_int); - virtual ~lar_solver(){ - for (auto c : m_constraints) - delete c; - for (auto t : m_terms) - delete t; - for (auto t : m_orig_terms) - delete t; - } + void add_new_var_to_core_fields_for_doubles(bool register_in_basis); -#include "util/lp/init_lar_solver.h" + void add_new_var_to_core_fields_for_mpq(bool register_in_basis); + + + var_index add_term_undecided(const vector> & coeffs, + const mpq &m_v); + + // terms + var_index add_term(const vector> & coeffs, + const mpq &m_v); + + void add_row_for_term(const lar_term * term, unsigned term_ext_index); + + void add_row_from_term_no_constraint(const lar_term * term, unsigned term_ext_index); + + void add_basic_var_to_core_fields(); + + constraint_index add_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side) ; + + void update_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index); + + void add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci); + + + void add_constraint_from_term_and_create_new_column_row(unsigned term_j, const lar_term* term, + lconstraint_kind kind, const mpq & right_side); + + void decide_on_strategy_and_adjust_initial_state(); + + void adjust_initial_state(); + + void adjust_initial_state_for_lu(); + + void adjust_initial_state_for_tableau_rows(); + + // this fills the last row of A_d and sets the basis column: -1 in the last column of the row + void fill_last_row_of_A_d(static_matrix & A, const lar_term* ls); + + void update_free_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_ind); + + void update_upper_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci); - numeric_pair const& get_value(var_index vi) const { return m_mpq_lar_core_solver.m_r_x[vi]; } + void update_boxed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci); + void update_low_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci); - bool is_term(var_index j) const { - return j >= m_terms_start_index && j - m_terms_start_index < m_terms.size(); - } + void update_fixed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci); + //end of init region + lp_settings & settings(); - unsigned adjust_term_index(unsigned j) const { - lean_assert(is_term(j)); - return j - m_terms_start_index; - } + lp_settings const & settings() const; + + void clear(); - bool use_lu() const { return m_settings.simplex_strategy() == simplex_strategy_enum::lu; } - - bool sizes_are_correct() const { - lean_assert(strategy_is_undecided() || !m_mpq_lar_core_solver.need_to_presolve_with_double_solver() || A_r().column_count() == A_d().column_count()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_column_types.size()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_x.size()); - return true; - } + lar_solver(); + void set_propagate_bounds_on_pivoted_rows_mode(bool v); + + virtual ~lar_solver(); + + numeric_pair const& get_value(var_index vi) const; + + bool is_term(var_index j) const; + + unsigned adjust_term_index(unsigned j) const; + + + bool use_lu() const; + bool sizes_are_correct() const; - void print_implied_bound(const implied_bound& be, std::ostream & out) const { - out << "implied bound\n"; - unsigned v = be.m_j; - if (is_term(v)) { - out << "it is a term number " << be.m_j << std::endl; - print_term(*m_orig_terms[be.m_j - m_terms_start_index], out); - } - else { - out << get_column_name(v); - } - out << " " << lconstraint_kind_string(be.kind()) << " " << be.m_bound << std::endl; - // for (auto & p : be.m_explanation) { - // out << p.first << " : "; - // print_constraint(p.second, out); - // } - - // m_mpq_lar_core_solver.m_r_solver.print_column_info(be.m_j< m_terms_start_index? be.m_j : adjust_term_index(be.m_j), out); - out << "end of implied bound" << std::endl; - } + void print_implied_bound(const implied_bound& be, std::ostream & out) const; - bool implied_bound_is_correctly_explained(implied_bound const & be, const vector> & explanation) const { - std::unordered_map coeff_map; - auto rs_of_evidence = zero_of_type(); - unsigned n_of_G = 0, n_of_L = 0; - bool strict = false; - for (auto & it : explanation) { - mpq coeff = it.first; - constraint_index con_ind = it.second; - const auto & constr = *m_constraints[con_ind]; - lconstraint_kind kind = coeff.is_pos() ? constr.m_kind : flip_kind(constr.m_kind); - register_in_map(coeff_map, constr, coeff); - if (kind == GT || kind == LT) - strict = true; - if (kind == GE || kind == GT) n_of_G++; - else if (kind == LE || kind == LT) n_of_L++; - rs_of_evidence += coeff*constr.m_right_side; - } - lean_assert(n_of_G == 0 || n_of_L == 0); - lconstraint_kind kind = n_of_G ? GE : (n_of_L ? LE : EQ); - if (strict) - kind = static_cast((static_cast(kind) / 2)); - - if (!is_term(be.m_j)) { - if (coeff_map.size() != 1) - return false; - auto it = coeff_map.find(be.m_j); - if (it == coeff_map.end()) return false; - mpq ratio = it->second; - if (ratio < zero_of_type()) { - kind = static_cast(-kind); - } - rs_of_evidence /= ratio; - } else { - const lar_term * t = m_orig_terms[adjust_term_index(be.m_j)]; - const auto first_coeff = *t->m_coeffs.begin(); - unsigned j = first_coeff.first; - auto it = coeff_map.find(j); - if (it == coeff_map.end()) - return false; - mpq ratio = it->second / first_coeff.second; - for (auto & p : t->m_coeffs) { - it = coeff_map.find(p.first); - if (it == coeff_map.end()) - return false; - if (p.second * ratio != it->second) - return false; - } - if (ratio < zero_of_type()) { - kind = static_cast(-kind); - } - rs_of_evidence /= ratio; - rs_of_evidence += t->m_v * ratio; - } - - return kind == be.kind() && rs_of_evidence == be.m_bound; - } - + bool implied_bound_is_correctly_explained(implied_bound const & be, const vector> & explanation) const; void analyze_new_bounds_on_row( unsigned row_index, - bound_propagator & bp) { - lean_assert(!use_tableau()); - iterator_on_pivot_row it(m_mpq_lar_core_solver.get_pivot_row(), m_mpq_lar_core_solver.m_r_basis[row_index]); - - bound_analyzer_on_row ra_pos(it, - zero_of_type>(), - row_index, - bp - ); - ra_pos.analyze(); - } + bound_propagator & bp); void analyze_new_bounds_on_row_tableau( unsigned row_index, bound_propagator & bp - ) { - - if (A_r().m_rows[row_index].size() > settings().max_row_length_for_bound_propagation) - return; - iterator_on_row it(A_r().m_rows[row_index]); - lean_assert(use_tableau()); - bound_analyzer_on_row::analyze_row(it, - zero_of_type>(), - row_index, - bp ); - } - void substitute_basis_var_in_terms_for_row(unsigned i) { - // todo : create a map from term basic vars to the rows where they are used - unsigned basis_j = m_mpq_lar_core_solver.m_r_solver.m_basis[i]; - for (unsigned k = 0; k < m_terms.size(); k++) { - if (term_is_used_as_row(k)) - continue; - if (!m_terms[k]->contains(basis_j)) - continue; - m_terms[k]->subst(basis_j, m_mpq_lar_core_solver.m_r_solver.m_pivot_row); - } - } + void substitute_basis_var_in_terms_for_row(unsigned i); - void calculate_implied_bounds_for_row(unsigned i, bound_propagator & bp) { - if(use_tableau()) { - analyze_new_bounds_on_row_tableau(i, bp); - } else { - m_mpq_lar_core_solver.calculate_pivot_row(i); - substitute_basis_var_in_terms_for_row(i); - analyze_new_bounds_on_row(i, bp); - } - } + void calculate_implied_bounds_for_row(unsigned i, bound_propagator & bp); - /* - void process_new_implied_evidence_for_low_bound( - implied_bound_explanation& implied_evidence, // not pushed yet - vector & bound_evidences, - std::unordered_map & improved_low_bounds) { - - unsigned existing_index; - if (try_get_val(improved_low_bounds, implied_evidence.m_j, existing_index)) { - // we are improving the existent bound - bound_evidences[existing_index] = fill_bound_evidence(implied_evidence); - } else { - improved_low_bounds[implied_evidence.m_j] = bound_evidences.size(); - bound_evidences.push_back(fill_bound_evidence(implied_evidence)); - } - } - - void fill_bound_evidence_on_term(implied_bound & ie, implied_bound& be) { - lean_assert(false); - } - void fill_implied_bound_on_row(implied_bound & ie, implied_bound& be) { - iterator_on_row it(A_r().m_rows[ie.m_row_or_term_index]); - mpq a; unsigned j; - bool toggle = ie.m_coeff_before_j_is_pos; - if (!ie.m_is_low_bound) - toggle = !toggle; - while (it.next(a, j)) { - if (j == ie.m_j) continue; - const ul_pair & ul = m_vars_to_ul_pairs[j]; - - if (is_neg(a)) { // so the monoid has a positive coeff on the right side - constraint_index witness = toggle ? ul.m_low_bound_witness : ul.m_upper_bound_witness; - lean_assert(is_valid(witness)); - be.m_explanation.emplace_back(a, witness); - } - } - } - */ - /* - implied_bound fill_implied_bound_for_low_bound(implied_bound& ie) { - implied_bound be(ie.m_j, ie.m_bound.y.is_zero() ? GE : GT, ie.m_bound.x); - if (is_term(ie.m_row_or_term_index)) { - fill_implied_bound_for_low_bound_on_term(ie, be); - } - else { - fill_implied_bound_for_low_bound_on_row(ie, be); - } - return be; - } - - implied_bound fill_implied_bound_for_upper_bound(implied_bound& implied_evidence) { - lean_assert(false); - - be.m_j = implied_evidence.m_j; - be.m_bound = implied_evidence.m_bound.x; - be.m_kind = implied_evidence.m_bound.y.is_zero() ? LE : LT; - for (auto t : implied_evidence.m_vector_of_bound_signatures) { - const ul_pair & ul = m_vars_to_ul_pairs[t.m_column_index]; - constraint_index witness = t.m_low_bound ? ul.m_low_bound_witness : ul.m_upper_bound_witness; - lean_assert(is_valid(witness)); - be.m_explanation.emplace_back(t.m_coeff, witness); - } - - } - */ - /* - void process_new_implied_evidence_for_upper_bound( - implied_bound& implied_evidence, - vector & implied_bounds, - std::unordered_map & improved_upper_bounds) { - unsigned existing_index; - if (try_get_val(improved_upper_bounds, implied_evidence.m_j, existing_index)) { - implied_bound & be = implied_bounds[existing_index]; - be.m_explanation.clear(); - // we are improving the existent bound improve the existing bound - be = fill_implied_bound_for_upper_bound(implied_evidence); - } else { - improved_upper_bounds[implied_evidence.m_j] = implied_bounds.size(); - implied_bounds.push_back(fill_implied_bound_for_upper_bound(implied_evidence)); - } - } - */ - // implied_bound * get_existing_ - linear_combination_iterator * create_new_iter_from_term(unsigned term_index) const { - lean_assert(false); // not implemented - return nullptr; - // new linear_combination_iterator_on_vector(m_terms[adjust_term_index(term_index)]->coeffs_as_vector()); - } + linear_combination_iterator * create_new_iter_from_term(unsigned term_index) const; - unsigned adjust_column_index_to_term_index(unsigned j) const { - unsigned ext_var_or_term = m_columns_to_ext_vars_or_term_indices[j]; - return ext_var_or_term < m_terms_start_index ? j : ext_var_or_term; - } + unsigned adjust_column_index_to_term_index(unsigned j) const; - void propagate_bounds_on_a_term(const lar_term& t, bound_propagator & bp, unsigned term_offset) { - lean_assert(false); // not implemented - } + void propagate_bounds_on_a_term(const lar_term& t, bound_propagator & bp, unsigned term_offset); - void explain_implied_bound(implied_bound & ib, bound_propagator & bp) { - unsigned i = ib.m_row_or_term_index; - int bound_sign = ib.m_is_low_bound? 1: -1; - int j_sign = (ib.m_coeff_before_j_is_pos ? 1 :-1) * bound_sign; - unsigned m_j = ib.m_j; - if (is_term(m_j)) { - m_j = m_ext_vars_to_columns[m_j]; - } - for (auto const& r : A_r().m_rows[i]) { - unsigned j = r.m_j; - mpq const& a = r.get_val(); - if (j == m_j) continue; - if (is_term(j)) { - j = m_ext_vars_to_columns[j]; - } - int a_sign = is_pos(a)? 1: -1; - int sign = j_sign * a_sign; - const ul_pair & ul = m_vars_to_ul_pairs[j]; - auto witness = sign > 0? ul.upper_bound_witness(): ul.low_bound_witness(); - lean_assert(is_valid(witness)); - bp.consume(a, witness); - } - // lean_assert(implied_bound_is_correctly_explained(ib, explanation)); - } + void explain_implied_bound(implied_bound & ib, bound_propagator & bp); - bool term_is_used_as_row(unsigned term) const { - lean_assert(is_term(term)); - return contains(m_ext_vars_to_columns, term); - } + bool term_is_used_as_row(unsigned term) const; - void propagate_bounds_on_terms(bound_propagator & bp) { - for (unsigned i = 0; i < m_terms.size(); i++) { - if (term_is_used_as_row(i + m_terms_start_index)) - continue; // this term is used a left side of a constraint, - // it was processed as a touched row if needed - propagate_bounds_on_a_term(*m_terms[i], bp, i); - } - } + void propagate_bounds_on_terms(bound_propagator & bp); // goes over touched rows and tries to induce bounds - void propagate_bounds_for_touched_rows(bound_propagator & bp) { - if (!use_tableau()) - return; // ! todo : enable bound propagaion here. The current bug is that after the pop - // the changed terms become incorrect! + void propagate_bounds_for_touched_rows(bound_propagator & bp); - for (unsigned i : m_rows_with_changed_bounds.m_index) { - calculate_implied_bounds_for_row(i, bp); - } - m_rows_with_changed_bounds.clear(); - if (!use_tableau()) { - propagate_bounds_on_terms(bp); - } - } + lp_status get_status() const; - lp_status get_status() const { return m_status;} + void set_status(lp_status s); - void set_status(lp_status s) {m_status = s;} - - lp_status find_feasible_solution() { - if (strategy_is_undecided()) - decide_on_strategy_and_adjust_initial_state(); - - m_mpq_lar_core_solver.m_r_solver.m_look_for_feasible_solution_only = true; - return solve(); - } + lp_status find_feasible_solution(); - lp_status solve() { - if (m_status == INFEASIBLE) { - return m_status; - } - solve_with_core_solver(); - if (m_status != INFEASIBLE) { - if (m_settings.bound_propagation()) - detect_rows_with_changed_bounds(); - } - - m_columns_with_changed_bound.clear(); - return m_status; - } + lp_status solve(); - void fill_explanation_from_infeasible_column(vector> & evidence) const{ - - // this is the case when the lower bound is in conflict with the upper one - const ul_pair & ul = m_vars_to_ul_pairs[m_infeasible_column_index]; - evidence.push_back(std::make_pair(numeric_traits::one(), ul.upper_bound_witness())); - evidence.push_back(std::make_pair(-numeric_traits::one(), ul.low_bound_witness())); - } + void fill_explanation_from_infeasible_column(explanation_t & evidence) const; - unsigned get_total_iterations() const { return m_mpq_lar_core_solver.m_r_solver.total_iterations(); } + unsigned get_total_iterations() const; // see http://research.microsoft.com/projects/z3/smt07.pdf // This method searches for a feasible solution with as many different values of variables, reverenced in vars, as it can find // Attention, after a call to this method the non-basic variables don't necesserarly stick to their bounds anymore - vector get_list_of_all_var_indices() const { - vector ret; - for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_heading.size(); j++) - ret.push_back(j); - return ret; - } - void push() { - m_simplex_strategy = m_settings.simplex_strategy(); - m_simplex_strategy.push(); - m_status.push(); - m_vars_to_ul_pairs.push(); - m_infeasible_column_index.push(); - m_mpq_lar_core_solver.push(); - m_term_count = m_terms.size(); - m_term_count.push(); - m_constraint_count = m_constraints.size(); - m_constraint_count.push(); - } + vector get_list_of_all_var_indices() const; + void push(); - static void clean_large_elements_after_pop(unsigned n, int_set& set) { - vector to_remove; - for (unsigned j: set.m_index) - if (j >= n) - to_remove.push_back(j); - for (unsigned j : to_remove) - set.erase(j); - } + static void clean_large_elements_after_pop(unsigned n, int_set& set); - static void shrink_inf_set_after_pop(unsigned n, int_set & set) { - clean_large_elements_after_pop(n, set); - set.resize(n); - } + static void shrink_inf_set_after_pop(unsigned n, int_set & set); - void pop(unsigned k) { - int n_was = static_cast(m_ext_vars_to_columns.size()); - m_status.pop(k); - m_infeasible_column_index.pop(k); - unsigned n = m_vars_to_ul_pairs.peek_size(k); - for (unsigned j = n_was; j-- > n;) - m_ext_vars_to_columns.erase(m_columns_to_ext_vars_or_term_indices[j]); - m_columns_to_ext_vars_or_term_indices.resize(n); - if (m_settings.use_tableau()) { - pop_tableau(); - } - m_vars_to_ul_pairs.pop(k); - - m_mpq_lar_core_solver.pop(k); - clean_large_elements_after_pop(n, m_columns_with_changed_bound); - unsigned m = A_r().row_count(); - clean_large_elements_after_pop(m, m_rows_with_changed_bounds); - clean_inf_set_of_r_solver_after_pop(); - lean_assert(m_settings.simplex_strategy() == simplex_strategy_enum::undecided || - (!use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); - - - lean_assert(ax_is_correct()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.inf_set_is_correct()); - m_constraint_count.pop(k); - for (unsigned i = m_constraint_count; i < m_constraints.size(); i++) - delete m_constraints[i]; - - m_constraints.resize(m_constraint_count); - m_term_count.pop(k); - for (unsigned i = m_term_count; i < m_terms.size(); i++) { - delete m_terms[i]; - delete m_orig_terms[i]; - } - m_terms.resize(m_term_count); - m_orig_terms.resize(m_term_count); - m_simplex_strategy.pop(k); - m_settings.simplex_strategy() = m_simplex_strategy; - lean_assert(sizes_are_correct()); - lean_assert((!m_settings.use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); - } + void pop(unsigned k); - vector get_all_constraint_indices() const { - vector ret; - constraint_index i = 0; - while ( i < m_constraints.size()) - ret.push_back(i++); - return ret; - } + vector get_all_constraint_indices() const; bool maximize_term_on_tableau(const vector> & term, - impq &term_max) { - if (settings().simplex_strategy() == simplex_strategy_enum::undecided) - decide_on_strategy_and_adjust_initial_state(); - - m_mpq_lar_core_solver.solve(); - if (m_mpq_lar_core_solver.m_r_solver.get_status() == UNBOUNDED) - return false; + impq &term_max); - term_max = 0; - for (auto & p : term) - term_max += p.first * m_mpq_lar_core_solver.m_r_x[p.second]; - - return true; - } - - bool costs_are_zeros_for_r_solver() const { - for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_solver.m_costs.size(); j++) { - lean_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_costs[j])); - } - return true; - } - bool reduced_costs_are_zeroes_for_r_solver() const { - for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_solver.m_d.size(); j++) { - lean_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_d[j])); - } - return true; - } + bool costs_are_zeros_for_r_solver() const; + bool reduced_costs_are_zeroes_for_r_solver() const; - void set_costs_to_zero(const vector> & term) { - auto & rslv = m_mpq_lar_core_solver.m_r_solver; - auto & jset = m_mpq_lar_core_solver.m_r_solver.m_inf_set; // hijack this set that should be empty right now - lean_assert(jset.m_index.size()==0); - - for (auto & p : term) { - unsigned j = p.second; - rslv.m_costs[j] = zero_of_type(); - int i = rslv.m_basis_heading[j]; - if (i < 0) - jset.insert(j); - else { - for (auto & rc : A_r().m_rows[i]) - jset.insert(rc.m_j); - } - } + void set_costs_to_zero(const vector> & term); - for (unsigned j : jset.m_index) - rslv.m_d[j] = zero_of_type(); - - jset.clear(); - - lean_assert(reduced_costs_are_zeroes_for_r_solver()); - lean_assert(costs_are_zeros_for_r_solver()); - } - - void prepare_costs_for_r_solver(const vector> & term) { - - auto & rslv = m_mpq_lar_core_solver.m_r_solver; - rslv.m_using_infeas_costs = false; - lean_assert(costs_are_zeros_for_r_solver()); - lean_assert(reduced_costs_are_zeroes_for_r_solver()); - rslv.m_costs.resize(A_r().column_count(), zero_of_type()); - for (auto & p : term) { - unsigned j = p.second; - rslv.m_costs[j] = p.first; - if (rslv.m_basis_heading[j] < 0) - rslv.m_d[j] += p.first; - else - rslv.update_reduced_cost_for_basic_column_cost_change(- p.first, j); - } - lean_assert(rslv.reduced_costs_are_correct_tableau()); - } + void prepare_costs_for_r_solver(const vector> & term); bool maximize_term_on_corrected_r_solver(const vector> & term, - impq &term_max) { - settings().backup_costs = false; - switch (settings().simplex_strategy()) { - case simplex_strategy_enum::tableau_rows: - prepare_costs_for_r_solver(term); - settings().simplex_strategy() = simplex_strategy_enum::tableau_costs; - { - bool ret = maximize_term_on_tableau(term, term_max); - settings().simplex_strategy() = simplex_strategy_enum::tableau_rows; - set_costs_to_zero(term); - m_mpq_lar_core_solver.m_r_solver.set_status(OPTIMAL); - return ret; - } - case simplex_strategy_enum::tableau_costs: - prepare_costs_for_r_solver(term); - { - bool ret = maximize_term_on_tableau(term, term_max); - set_costs_to_zero(term); - m_mpq_lar_core_solver.m_r_solver.set_status(OPTIMAL); - return ret; - } - - case simplex_strategy_enum::lu: - lean_assert(false); // not implemented - return false; - default: - lean_unreachable(); // wrong mode - } - return false; - } + impq &term_max); // starting from a given feasible state look for the maximum of the term // return true if found and false if unbounded bool maximize_term(const vector> & term, - impq &term_max) { - lean_assert(m_mpq_lar_core_solver.m_r_solver.current_x_is_feasible()); - m_mpq_lar_core_solver.m_r_solver.m_look_for_feasible_solution_only = false; - return maximize_term_on_corrected_r_solver(term, term_max); - } + impq &term_max); - const lar_term & get_term(unsigned j) const { - lean_assert(j >= m_terms_start_index); - return *m_terms[j - m_terms_start_index]; - } + const lar_term & get_term(unsigned j) const; - void pop_core_solver_params() { - pop_core_solver_params(1); - } + void pop_core_solver_params(); - void pop_core_solver_params(unsigned k) { - A_r().pop(k); - A_d().pop(k); - } + void pop_core_solver_params(unsigned k); - void set_upper_bound_witness(var_index j, constraint_index ci) { - ul_pair ul = m_vars_to_ul_pairs[j]; - ul.upper_bound_witness() = ci; - m_vars_to_ul_pairs[j] = ul; - } + void set_upper_bound_witness(var_index j, constraint_index ci); - void set_low_bound_witness(var_index j, constraint_index ci) { - ul_pair ul = m_vars_to_ul_pairs[j]; - ul.low_bound_witness() = ci; - m_vars_to_ul_pairs[j] = ul; - } + void set_low_bound_witness(var_index j, constraint_index ci); - void substitute_terms(const mpq & mult, - const vector>& left_side_with_terms, - vector> &left_side, mpq & right_side) const { - for (auto & t : left_side_with_terms) { - if (t.second < m_terms_start_index) { - lean_assert(t.second < A_r().column_count()); - left_side.push_back(std::pair(mult * t.first, t.second)); - } else { - const lar_term & term = * m_terms[adjust_term_index(t.second)]; - substitute_terms(mult * t.first, left_side_with_terms, left_side, right_side); - right_side -= mult * term.m_v; - } - } - } + void substitute_terms_in_linear_expression( const vector>& left_side_with_terms, + vector> &left_side, mpq & right_side) const; - void detect_rows_of_bound_change_column_for_nbasic_column(unsigned j) { - if (A_r().row_count() != m_column_buffer.data_size()) - m_column_buffer.resize(A_r().row_count()); - else - m_column_buffer.clear(); - lean_assert(m_column_buffer.size() == 0 && m_column_buffer.is_OK()); - - m_mpq_lar_core_solver.m_r_solver.solve_Bd(j, m_column_buffer); - for (unsigned i : m_column_buffer.m_index) - m_rows_with_changed_bounds.insert(i); - } + void detect_rows_of_bound_change_column_for_nbasic_column(unsigned j); - void detect_rows_of_bound_change_column_for_nbasic_column_tableau(unsigned j) { - for (auto & rc : m_mpq_lar_core_solver.m_r_A.m_columns[j]) - m_rows_with_changed_bounds.insert(rc.m_i); - } + void detect_rows_of_bound_change_column_for_nbasic_column_tableau(unsigned j); - bool use_tableau() const { return m_settings.use_tableau(); } + bool use_tableau() const; - bool use_tableau_costs() const { - return m_settings.simplex_strategy() == simplex_strategy_enum::tableau_costs; - } + bool use_tableau_costs() const; - void detect_rows_of_column_with_bound_change(unsigned j) { - if (m_mpq_lar_core_solver.m_r_heading[j] >= 0) { // it is a basic column - // just mark the row at touched and exit - m_rows_with_changed_bounds.insert(m_mpq_lar_core_solver.m_r_heading[j]); - return; - } + void detect_rows_of_column_with_bound_change(unsigned j); - if (use_tableau()) - detect_rows_of_bound_change_column_for_nbasic_column_tableau(j); - else - detect_rows_of_bound_change_column_for_nbasic_column(j); - } + void adjust_x_of_column(unsigned j); - void adjust_x_of_column(unsigned j) { - lean_assert(false); - } - - bool row_is_correct(unsigned i) const { - numeric_pair r = zero_of_type>(); - for (const auto & c : A_r().m_rows[i]) - r += c.m_value * m_mpq_lar_core_solver.m_r_x[c.m_j]; - return is_zero(r); - } + bool row_is_correct(unsigned i) const; - bool ax_is_correct() const { - for (unsigned i = 0; i < A_r().row_count(); i++) { - if (!row_is_correct(i)) - return false; - } - return true; - } + bool ax_is_correct() const; - bool tableau_with_costs() const { - return m_settings.simplex_strategy() == simplex_strategy_enum::tableau_costs; - } + bool tableau_with_costs() const; - bool costs_are_used() const { - return m_settings.simplex_strategy() != simplex_strategy_enum::tableau_rows; - } + bool costs_are_used() const; - void change_basic_x_by_delta_on_column(unsigned j, const numeric_pair & delta) { - if (use_tableau()) { - for (const auto & c : A_r().m_columns[j]) { - unsigned bj = m_mpq_lar_core_solver.m_r_basis[c.m_i]; - m_mpq_lar_core_solver.m_r_x[bj] -= A_r().get_val(c) * delta; - if (tableau_with_costs()) { - m_basic_columns_with_changed_cost.insert(bj); - } - m_mpq_lar_core_solver.m_r_solver.update_column_in_inf_set(bj); - } - } else { - m_column_buffer.clear(); - m_column_buffer.resize(A_r().row_count()); - m_mpq_lar_core_solver.m_r_solver.solve_Bd(j, m_column_buffer); - for (unsigned i : m_column_buffer.m_index) { - unsigned bj = m_mpq_lar_core_solver.m_r_basis[i]; - m_mpq_lar_core_solver.m_r_x[bj] -= m_column_buffer[i] * delta; - m_mpq_lar_core_solver.m_r_solver.update_column_in_inf_set(bj); - } - } - } + void change_basic_x_by_delta_on_column(unsigned j, const numeric_pair & delta); - void update_x_and_inf_costs_for_column_with_changed_bounds(unsigned j) { - if (m_mpq_lar_core_solver.m_r_heading[j] >= 0) { - if (costs_are_used()) { - bool was_infeas = m_mpq_lar_core_solver.m_r_solver.m_inf_set.contains(j); - m_mpq_lar_core_solver.m_r_solver.update_column_in_inf_set(j); - if (was_infeas != m_mpq_lar_core_solver.m_r_solver.m_inf_set.contains(j)) - m_basic_columns_with_changed_cost.insert(j); - } else { - m_mpq_lar_core_solver.m_r_solver.update_column_in_inf_set(j); - } - } else { - numeric_pair delta; - if (m_mpq_lar_core_solver.m_r_solver.make_column_feasible(j, delta)) - change_basic_x_by_delta_on_column(j, delta); - } - } + void update_x_and_inf_costs_for_column_with_changed_bounds(unsigned j); - void detect_rows_with_changed_bounds_for_column(unsigned j) { - if (m_mpq_lar_core_solver.m_r_heading[j] >= 0) { - m_rows_with_changed_bounds.insert(m_mpq_lar_core_solver.m_r_heading[j]); - return; - } - - if (use_tableau()) - detect_rows_of_bound_change_column_for_nbasic_column_tableau(j); - else - detect_rows_of_bound_change_column_for_nbasic_column(j); - } + void detect_rows_with_changed_bounds_for_column(unsigned j); - void detect_rows_with_changed_bounds() { - for (auto j : m_columns_with_changed_bound.m_index) - detect_rows_with_changed_bounds_for_column(j); - } + void detect_rows_with_changed_bounds(); - void update_x_and_inf_costs_for_columns_with_changed_bounds() { - for (auto j : m_columns_with_changed_bound.m_index) - update_x_and_inf_costs_for_column_with_changed_bounds(j); - } + void update_x_and_inf_costs_for_columns_with_changed_bounds(); - void update_x_and_inf_costs_for_columns_with_changed_bounds_tableau() { - lean_assert(ax_is_correct()); - for (auto j : m_columns_with_changed_bound.m_index) - update_x_and_inf_costs_for_column_with_changed_bounds(j); - - if (tableau_with_costs()) { - for (unsigned j : m_basic_columns_with_changed_cost.m_index) - m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); - lean_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); - } - } + void update_x_and_inf_costs_for_columns_with_changed_bounds_tableau(); - void solve_with_core_solver() { - if (!use_tableau()) - add_last_rows_to_lu(m_mpq_lar_core_solver.m_r_solver); - if (m_mpq_lar_core_solver.need_to_presolve_with_double_solver()) { - add_last_rows_to_lu(m_mpq_lar_core_solver.m_d_solver); - } - m_mpq_lar_core_solver.prefix_r(); - if (costs_are_used()) { - m_basic_columns_with_changed_cost.clear(); - m_basic_columns_with_changed_cost.resize(m_mpq_lar_core_solver.m_r_x.size()); - } - if (use_tableau()) - update_x_and_inf_costs_for_columns_with_changed_bounds_tableau(); - else - update_x_and_inf_costs_for_columns_with_changed_bounds(); - m_mpq_lar_core_solver.solve(); - set_status(m_mpq_lar_core_solver.m_r_solver.get_status()); - lean_assert(m_status != OPTIMAL || all_constraints_hold()); - } + void solve_with_core_solver(); - numeric_pair get_basic_var_value_from_row_directly(unsigned i) { - numeric_pair r = zero_of_type>(); - - unsigned bj = m_mpq_lar_core_solver.m_r_solver.m_basis[i]; - for (const auto & c: A_r().m_rows[i]) { - if (c.m_j == bj) continue; - const auto & x = m_mpq_lar_core_solver.m_r_x[c.m_j]; - if (!is_zero(x)) - r -= c.m_value * x; - } - return r; - } + numeric_pair get_basic_var_value_from_row_directly(unsigned i); - numeric_pair get_basic_var_value_from_row(unsigned i) { - if (settings().use_tableau()) { - return get_basic_var_value_from_row_directly(i); - } - - numeric_pair r = zero_of_type>(); - m_mpq_lar_core_solver.calculate_pivot_row(i); - for (unsigned j : m_mpq_lar_core_solver.m_r_solver.m_pivot_row.m_index) { - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); - r -= m_mpq_lar_core_solver.m_r_solver.m_pivot_row.m_data[j] * m_mpq_lar_core_solver.m_r_x[j]; - } - return r; - } + numeric_pair get_basic_var_value_from_row(unsigned i); template - void add_last_rows_to_lu(lp_primal_core_solver & s) { - auto & f = s.m_factorization; - if (f != nullptr) { - auto columns_to_replace = f->get_set_of_columns_to_replace_for_add_last_rows(s.m_basis_heading); - if (f->m_refactor_counter + columns_to_replace.size() >= 200 || f->has_dense_submatrix()) { - delete f; - f = nullptr; - } else { - f->add_last_rows_to_B(s.m_basis_heading, columns_to_replace); - } - } - if (f == nullptr) { - init_factorization(f, s.m_A, s.m_basis, m_settings); - if (f->get_status() != LU_status::OK) { - delete f; - f = nullptr; - } - } - - } + void add_last_rows_to_lu(lp_primal_core_solver & s); - bool x_is_correct() const { - if (m_mpq_lar_core_solver.m_r_x.size() != A_r().column_count()) { - // std::cout << "the size is off " << m_r_solver.m_x.size() << ", " << A().column_count() << std::endl; - return false; - } - for (unsigned i = 0; i < A_r().row_count(); i++) { - numeric_pair delta = A_r().dot_product_with_row(i, m_mpq_lar_core_solver.m_r_x); - if (!delta.is_zero()) { - // std::cout << "x is off ("; - // std::cout << "m_b[" << i << "] = " << m_b[i] << " "; - // std::cout << "left side = " << A().dot_product_with_row(i, m_r_solver.m_x) << ' '; - // std::cout << "delta = " << delta << ' '; - // std::cout << "iters = " << total_iterations() << ")" << std::endl; - // std::cout << "row " << i << " is off" << std::endl; - return false; - } - } - return true;; - - } + bool x_is_correct() const; - bool var_is_registered(var_index vj) const { - if (vj >= m_terms_start_index) { - if (vj - m_terms_start_index >= m_terms.size()) - return false; - } else if ( vj >= A_r().column_count()) { - return false; - } - return true; - } + bool var_is_registered(var_index vj) const; - unsigned constraint_stack_size() const { - return m_constraint_count.stack_size(); - } + unsigned constraint_stack_size() const; - void fill_last_row_of_A_r(static_matrix> & A, const lar_term * ls) { - lean_assert(A.row_count() > 0); - lean_assert(A.column_count() > 0); - unsigned last_row = A.row_count() - 1; - lean_assert(A.m_rows[last_row].size() == 0); - for (auto & t : ls->m_coeffs) { - lean_assert(!is_zero(t.second)); - var_index j = t.first; - A.set(last_row, j, - t.second); - } - unsigned basis_j = A.column_count() - 1; - A.set(last_row, basis_j, mpq(1)); - } + void fill_last_row_of_A_r(static_matrix> & A, const lar_term * ls); template - void create_matrix_A(static_matrix & matr) { - lean_assert(false); // not implemented - /* - unsigned m = number_or_nontrivial_left_sides(); - unsigned n = m_vec_of_canonic_left_sides.size(); - if (matr.row_count() == m && matr.column_count() == n) - return; - matr.init_empty_matrix(m, n); - copy_from_mpq_matrix(matr); - */ - } + void create_matrix_A(static_matrix & matr); template - void copy_from_mpq_matrix(static_matrix & matr) { - matr.m_rows.resize(A_r().row_count()); - matr.m_columns.resize(A_r().column_count()); - for (unsigned i = 0; i < matr.row_count(); i++) { - for (auto & it : A_r().m_rows[i]) { - matr.set(i, it.m_j, convert_struct::convert(it.get_val())); - } - } - } + void copy_from_mpq_matrix(static_matrix & matr); - bool try_to_set_fixed(column_info & ci) { - if (ci.upper_bound_is_set() && ci.low_bound_is_set() && ci.get_upper_bound() == ci.get_low_bound() && !ci.is_fixed()) { - ci.set_fixed_value(ci.get_upper_bound()); - return true; - } - return false; - } + bool try_to_set_fixed(column_info & ci); - column_type get_column_type(const column_info & ci) { - auto ret = ci.get_column_type_no_flipping(); - if (ret == column_type::boxed) { // changing boxed to fixed because of the no span - if (ci.get_low_bound() == ci.get_upper_bound()) - ret = column_type::fixed; - } - return ret; - } + column_type get_column_type(const column_info & ci); - std::string get_column_name(unsigned j) const { - if (j >= m_terms_start_index) - return std::string("_t") + T_to_string(j); - if (j >= m_columns_to_ext_vars_or_term_indices.size()) - return std::string("_s") + T_to_string(j); + std::string get_column_name(unsigned j) const; - return std::string("v") + T_to_string(m_columns_to_ext_vars_or_term_indices[j]); - } + bool all_constrained_variables_are_registered(const vector>& left_side); - bool all_constrained_variables_are_registered(const vector>& left_side) { - for (auto it : left_side) { - if (! var_is_registered(it.second)) - return false; - } - return true; - } + constraint_index add_constraint(const vector>& left_side_with_terms, lconstraint_kind kind_par, const mpq& right_side_parm); + bool all_constraints_hold() const; + bool constraint_holds(const lar_base_constraint & constr, std::unordered_map & var_map) const; + bool the_relations_are_of_same_type(const vector> & evidence, lconstraint_kind & the_kind_of_sum) const; - constraint_index add_constraint(const vector>& left_side_with_terms, lconstraint_kind kind_par, const mpq& right_side_parm) { - /* - mpq rs = right_side_parm; - vector> left_side; - substitute_terms(one_of_type(), left_side_with_terms, left_side, rs); - lean_assert(left_side.size() > 0); - lean_assert(all_constrained_variables_are_registered(left_side)); - lar_constraint original_constr(left_side, kind_par, rs); - unsigned j; // j is the index of the basic variables corresponding to the left side - canonic_left_side ls = create_or_fetch_canonic_left_side(left_side, j); - mpq ratio = find_ratio_of_original_constraint_to_normalized(ls, original_constr); - auto kind = ratio.is_neg() ? flip_kind(kind_par) : kind_par; - rs/= ratio; - lar_normalized_constraint normalized_constraint(ls, ratio, kind, rs, original_constr); - m_constraints.push_back(normalized_constraint); - constraint_index constr_ind = m_constraints.size() - 1; - update_column_type_and_bound(j, kind, rs, constr_ind); - return constr_ind; - */ - lean_assert(false); // not implemented - return 0; - } + static void register_in_map(std::unordered_map & coeffs, const lar_base_constraint & cn, const mpq & a); + static void register_one_coeff_in_map(std::unordered_map & coeffs, const mpq & a, unsigned j); - bool all_constraints_hold() const { - if (m_settings.get_cancel_flag()) - return true; - std::unordered_map var_map; - get_model(var_map); + + bool the_left_sides_sum_to_zero(const vector> & evidence) const; + + bool the_right_sides_do_not_sum_to_zero(const vector> & evidence); + + bool explanation_is_correct(const vector>& explanation) const; + + bool inf_explanation_is_correct() const; + + mpq sum_of_right_sides_of_explanation(const vector> & explanation) const; + + bool has_lower_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict); - for (unsigned i = 0; i < m_constraints.size(); i++) { - if (!constraint_holds(*m_constraints[i], var_map)) { - print_constraint(i, std::cout); - return false; - } - } - return true; - } - - bool constraint_holds(const lar_base_constraint & constr, std::unordered_map & var_map) const { - mpq left_side_val = get_left_side_val(constr, var_map); - switch (constr.m_kind) { - case LE: return left_side_val <= constr.m_right_side; - case LT: return left_side_val < constr.m_right_side; - case GE: return left_side_val >= constr.m_right_side; - case GT: return left_side_val > constr.m_right_side; - case EQ: return left_side_val == constr.m_right_side; - default: - lean_unreachable(); - } - return false; // it is unreachable - } + bool has_upper_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict); - - - - - - bool the_relations_are_of_same_type(const vector> & evidence, lconstraint_kind & the_kind_of_sum) const { - unsigned n_of_G = 0, n_of_L = 0; - bool strict = false; - for (auto & it : evidence) { - mpq coeff = it.first; - constraint_index con_ind = it.second; - lconstraint_kind kind = coeff.is_pos() ? - m_constraints[con_ind]->m_kind : - flip_kind(m_constraints[con_ind]->m_kind); - if (kind == GT || kind == LT) - strict = true; - if (kind == GE || kind == GT) n_of_G++; - else if (kind == LE || kind == LT) n_of_L++; - } - the_kind_of_sum = n_of_G ? GE : (n_of_L ? LE : EQ); - if (strict) - the_kind_of_sum = static_cast((static_cast(the_kind_of_sum) / 2)); - - return n_of_G == 0 || n_of_L == 0; - } - - static void register_in_map(std::unordered_map & coeffs, const lar_base_constraint & cn, const mpq & a) { - for (auto & it : cn.get_left_side_coefficients()) { - unsigned j = it.second; - auto p = coeffs.find(j); - if (p == coeffs.end()) - coeffs[j] = it.first * a; - else { - p->second += it.first * a; - if (p->second.is_zero()) - coeffs.erase(p); - } - } - } - bool the_left_sides_sum_to_zero(const vector> & evidence) const { - std::unordered_map coeff_map; - for (auto & it : evidence) { - mpq coeff = it.first; - constraint_index con_ind = it.second; - lean_assert(con_ind < m_constraints.size()); - register_in_map(coeff_map, *m_constraints[con_ind], coeff); - } - - if (!coeff_map.empty()) { - std::cout << "left side = "; - vector> t; - for (auto & it : coeff_map) { - t.push_back(std::make_pair(it.second, it.first)); - } - print_linear_combination_of_column_indices(t, std::cout); - std::cout << std::endl; - return false; - } - - return true; - } - - bool the_right_sides_do_not_sum_to_zero(const vector> & evidence) { - mpq ret = numeric_traits::zero(); - for (auto & it : evidence) { - mpq coeff = it.first; - constraint_index con_ind = it.second; - lean_assert(con_ind < m_constraints.size()); - const lar_constraint & constr = *m_constraints[con_ind]; - ret += constr.m_right_side * coeff; - } - return !numeric_traits::is_zero(ret); - } - - bool explanation_is_correct(const vector>& explanation) const { -#ifdef LEAN_DEBUG - lconstraint_kind kind; - lean_assert(the_relations_are_of_same_type(explanation, kind)); - lean_assert(the_left_sides_sum_to_zero(explanation)); - mpq rs = sum_of_right_sides_of_explanation(explanation); - switch (kind) { - case LE: lean_assert(rs < zero_of_type()); - break; - case LT: lean_assert(rs <= zero_of_type()); - break; - case GE: lean_assert(rs > zero_of_type()); - break; - case GT: lean_assert(rs >= zero_of_type()); - break; - case EQ: lean_assert(rs != zero_of_type()); - break; - default: - lean_assert(false); - return false; - } -#endif - return true; - } - - bool inf_explanation_is_correct() const { -#ifdef LEAN_DEBUG - vector> explanation; - get_infeasibility_explanation(explanation); - return explanation_is_correct(explanation); -#endif - return true; - } - - mpq sum_of_right_sides_of_explanation(const vector> & explanation) const { - mpq ret = numeric_traits::zero(); - for (auto & it : explanation) { - mpq coeff = it.first; - constraint_index con_ind = it.second; - lean_assert(con_ind < m_constraints.size()); - ret += (m_constraints[con_ind]->m_right_side - m_constraints[con_ind]->get_free_coeff_of_left_side()) * coeff; - } - return ret; - } - - bool has_lower_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) { - - if (var >= m_vars_to_ul_pairs.size()) { - // TBD: bounds on terms could also be used, caller may have to track these. - return false; - } - const ul_pair & ul = m_vars_to_ul_pairs[var]; - ci = ul.low_bound_witness(); - if (ci != static_cast(-1)) { - auto& p = m_mpq_lar_core_solver.m_r_low_bounds()[var]; - value = p.x; - is_strict = p.y.is_pos(); - return true; - } - else { - return false; - } - } - - bool has_upper_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) { - - if (var >= m_vars_to_ul_pairs.size()) { - // TBD: bounds on terms could also be used, caller may have to track these. - return false; - } - const ul_pair & ul = m_vars_to_ul_pairs[var]; - ci = ul.upper_bound_witness(); - if (ci != static_cast(-1)) { - auto& p = m_mpq_lar_core_solver.m_r_upper_bounds()[var]; - value = p.x; - is_strict = p.y.is_neg(); - return true; - } - else { - return false; - } - } - - - void get_infeasibility_explanation(vector> & explanation) const { - explanation.clear(); - if (m_infeasible_column_index != -1) { - fill_explanation_from_infeasible_column(explanation); - return; - } - if (m_mpq_lar_core_solver.get_infeasible_sum_sign() == 0) { - return; - } - // the infeasibility sign - int inf_sign; - auto inf_row = m_mpq_lar_core_solver.get_infeasibility_info(inf_sign); - get_infeasibility_explanation_for_inf_sign(explanation, inf_row, inf_sign); - lean_assert(explanation_is_correct(explanation)); - } + void get_infeasibility_explanation(vector> & explanation) const; void get_infeasibility_explanation_for_inf_sign( vector> & explanation, const vector> & inf_row, - int inf_sign) const { - - for (auto & it : inf_row) { - mpq coeff = it.first; - unsigned j = it.second; - - int adj_sign = coeff.is_pos() ? inf_sign : -inf_sign; - const ul_pair & ul = m_vars_to_ul_pairs[j]; - - constraint_index bound_constr_i = adj_sign < 0 ? ul.upper_bound_witness() : ul.low_bound_witness(); - lean_assert(bound_constr_i < m_constraints.size()); - explanation.push_back(std::make_pair(coeff, bound_constr_i)); - } - } + int inf_sign) const; - void get_model(std::unordered_map & variable_values) const { - mpq delta = mpq(1, 2); // start from 0.5 to have less clashes - lean_assert(m_status == OPTIMAL); - unsigned i; - do { - - // different pairs have to produce different singleton values - std::unordered_set set_of_different_pairs; - std::unordered_set set_of_different_singles; - delta = m_mpq_lar_core_solver.find_delta_for_strict_bounds(delta); - for (i = 0; i < m_mpq_lar_core_solver.m_r_x.size(); i++ ) { - const numeric_pair & rp = m_mpq_lar_core_solver.m_r_x[i]; - set_of_different_pairs.insert(rp); - mpq x = rp.x + delta * rp.y; - set_of_different_singles.insert(x); - if (set_of_different_pairs.size() - != set_of_different_singles.size()) { - delta /= mpq(2); - break; - } - - variable_values[i] = x; - } - } while (i != m_mpq_lar_core_solver.m_r_x.size()); - } + void get_model(std::unordered_map & variable_values) const; - std::string get_variable_name(var_index vi) const { - return get_column_name(vi); - } + std::string get_variable_name(var_index vi) const; // ********** print region start - void print_constraint(constraint_index ci, std::ostream & out) const { - if (ci >= m_constraints.size()) { - out << "constraint " << T_to_string(ci) << " is not found"; - out << std::endl; - return; - } + void print_constraint(constraint_index ci, std::ostream & out) const; - print_constraint(m_constraints[ci], out); - } + void print_constraints(std::ostream& out) const ; - void print_constraints(std::ostream& out) const { - for (auto c : m_constraints) { - print_constraint(c, out); - } - } + void print_terms(std::ostream& out) const ; - void print_terms(std::ostream& out) const { - for (auto it : m_terms) { - print_term(*it, out); - out << "\n"; - } - } + void print_left_side_of_constraint(const lar_base_constraint * c, std::ostream & out) const; - void print_left_side_of_constraint(const lar_base_constraint * c, std::ostream & out) const { - print_linear_combination_of_column_indices(c->get_left_side_coefficients(), out); - mpq free_coeff = c->get_free_coeff_of_left_side(); - if (!is_zero(free_coeff)) - out << " + " << free_coeff; - - } + void print_term(lar_term const& term, std::ostream & out) const; - void print_term(lar_term const& term, std::ostream & out) const { - if (!numeric_traits::is_zero(term.m_v)) { - out << term.m_v << " + "; - } - print_linear_combination_of_column_indices(term.coeffs_as_vector(), out); - } + mpq get_left_side_val(const lar_base_constraint & cns, const std::unordered_map & var_map) const; - mpq get_left_side_val(const lar_base_constraint & cns, const std::unordered_map & var_map) const { - mpq ret = cns.get_free_coeff_of_left_side(); - for (auto & it : cns.get_left_side_coefficients()) { - var_index j = it.second; - auto vi = var_map.find(j); - lean_assert(vi != var_map.end()); - ret += it.first * vi->second; - } - return ret; - } + void print_constraint(const lar_base_constraint * c, std::ostream & out) const; - void print_constraint(const lar_base_constraint * c, std::ostream & out) const { - print_left_side_of_constraint(c, out); - out << " " << lconstraint_kind_string(c->m_kind) << " " << c->m_right_side << std::endl; - } + void fill_var_set_for_random_update(unsigned sz, var_index const * vars, vector& column_list); - void fill_var_set_for_random_update(unsigned sz, var_index const * vars, vector& column_list) { - for (unsigned i = 0; i < sz; i++) { - var_index var = vars[i]; - if (var >= m_terms_start_index) { // handle the term - for (auto & it : m_terms[var - m_terms_start_index]->m_coeffs) { - column_list.push_back(it.first); - } - } else { - column_list.push_back(var); - } - } - } + void random_update(unsigned sz, var_index const * vars); + void pivot_fixed_vars_from_basis(); + void pop(); + bool column_represents_row_in_tableau(unsigned j); + void make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsigned i, unsigned j); + void remove_last_row_and_column_from_tableau(unsigned j); + void remove_last_column_from_tableau(unsigned j); - void random_update(unsigned sz, var_index const * vars) { - vector column_list; - fill_var_set_for_random_update(sz, vars, column_list); - random_updater ru(m_mpq_lar_core_solver, column_list); - ru.update(); - } + void remove_last_column_from_basis_tableau(unsigned j); + void remove_column_from_tableau(unsigned j); + void pop_tableau(); + void clean_inf_set_of_r_solver_after_pop(); + void shrink_explanation_to_minimum(vector> & explanation) const; - - void try_pivot_fixed_vars_from_basis() { - m_mpq_lar_core_solver.m_r_solver.pivot_fixed_vars_from_basis(); - } - - void pop() { - pop(1); - } - - - bool column_represents_row_in_tableau(unsigned j) { - return m_vars_to_ul_pairs()[j].m_i != static_cast(-1); - } - - void make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsigned i, unsigned j) { - // i, j - is the indices of the bottom-right element of the tableau - lean_assert(A_r().row_count() == i + 1 && A_r().column_count() == j + 1); - auto & last_column = A_r().m_columns[j]; - int non_zero_column_cell_index = -1; - for (unsigned k = last_column.size(); k-- > 0;){ - auto & cc = last_column[k]; - if (cc.m_i == i) - return; - non_zero_column_cell_index = k; - } - - lean_assert(non_zero_column_cell_index != -1); - lean_assert(static_cast(non_zero_column_cell_index) != i); - m_mpq_lar_core_solver.m_r_solver.transpose_rows_tableau(last_column[non_zero_column_cell_index].m_i, i); - } - - void remove_last_row_and_column_from_tableau(unsigned j) { - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); - auto & slv = m_mpq_lar_core_solver.m_r_solver; - unsigned i = A_r().row_count() - 1; //last row index - make_sure_that_the_bottom_right_elem_not_zero_in_tableau(i, j); - if (slv.m_basis_heading[j] < 0) { - slv.pivot_column_tableau(j, i); - } - - auto & last_row = A_r().m_rows[i]; - mpq &cost_j = m_mpq_lar_core_solver.m_r_solver.m_costs[j]; - bool cost_is_nz = !is_zero(cost_j); - for (unsigned k = last_row.size(); k-- > 0;) { - auto &rc = last_row[k]; - if (cost_is_nz) { - m_mpq_lar_core_solver.m_r_solver.m_d[rc.m_j] += cost_j*rc.get_val(); - } - - A_r().remove_element(last_row, rc); - } - lean_assert(last_row.size() == 0); - lean_assert(A_r().m_columns[j].size() == 0); - A_r().m_rows.pop_back(); - A_r().m_columns.pop_back(); - slv.m_b.pop_back(); - } - - void remove_last_column_from_tableau(unsigned j) { - lean_assert(j == A_r().column_count() - 1); - // the last column has to be empty - lean_assert(A_r().m_columns[j].size() == 0); - A_r().m_columns.pop_back(); - } - - void remove_last_column_from_basis_tableau(unsigned j) { - auto& rslv = m_mpq_lar_core_solver.m_r_solver; - int i = rslv.m_basis_heading[j]; - if (i >= 0) { // j is a basic var - int last_pos = static_cast(rslv.m_basis.size()) - 1; - lean_assert(last_pos >= 0); - if (i != last_pos) { - unsigned j_at_last_pos = rslv.m_basis[last_pos]; - rslv.m_basis[i] = j_at_last_pos; - rslv.m_basis_heading[j_at_last_pos] = i; - } - rslv.m_basis.pop_back(); // remove j from the basis - } else { - int last_pos = static_cast(rslv.m_nbasis.size()) - 1; - lean_assert(last_pos >= 0); - i = - 1 - i; - if (i != last_pos) { - unsigned j_at_last_pos = rslv.m_nbasis[last_pos]; - rslv.m_nbasis[i] = j_at_last_pos; - rslv.m_basis_heading[j_at_last_pos] = - i - 1; - } - rslv.m_nbasis.pop_back(); // remove j from the basis - } - rslv.m_basis_heading.pop_back(); - lean_assert(rslv.m_basis.size() == A_r().row_count()); - lean_assert(rslv.basis_heading_is_correct()); - } - - void remove_column_from_tableau(unsigned j) { - auto& rslv = m_mpq_lar_core_solver.m_r_solver; - lean_assert(j == A_r().column_count() - 1); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); - if (column_represents_row_in_tableau(j)) { - remove_last_row_and_column_from_tableau(j); - if (rslv.m_basis_heading[j] < 0) - rslv.change_basis_unconditionally(j, rslv.m_basis[A_r().row_count()]); // A_r().row_count() is the index of the last row in the basis still - } - else { - remove_last_column_from_tableau(j); - } - rslv.m_x.pop_back(); - rslv.m_d.pop_back(); - rslv.m_costs.pop_back(); - - remove_last_column_from_basis_tableau(j); - lean_assert(m_mpq_lar_core_solver.r_basis_is_OK()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); - } - - - void pop_tableau() { - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); - - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); - // We remove last variables starting from m_column_names.size() to m_vec_of_canonic_left_sides.size(). - // At this moment m_column_names is already popped - for (unsigned j = A_r().column_count(); j-- > m_columns_to_ext_vars_or_term_indices.size();) - remove_column_from_tableau(j); - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); - } - - - - - void clean_inf_set_of_r_solver_after_pop() { - vector became_feas; - clean_large_elements_after_pop(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.m_inf_set); - std::unordered_set basic_columns_with_changed_cost; - auto inf_index_copy = m_mpq_lar_core_solver.m_r_solver.m_inf_set.m_index; - for (auto j: inf_index_copy) { - if (m_mpq_lar_core_solver.m_r_heading[j] >= 0) { - continue; - } - // some basic columns might become non-basic - these columns need to be made feasible - numeric_pair delta; - if (m_mpq_lar_core_solver.m_r_solver.make_column_feasible(j, delta)) - change_basic_x_by_delta_on_column(j, delta); - became_feas.push_back(j); - } - - for (unsigned j : became_feas) { - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); - m_mpq_lar_core_solver.m_r_solver.m_d[j] -= m_mpq_lar_core_solver.m_r_solver.m_costs[j]; - m_mpq_lar_core_solver.m_r_solver.m_costs[j] = zero_of_type(); - m_mpq_lar_core_solver.m_r_solver.m_inf_set.erase(j); - } - became_feas.clear(); - for (unsigned j : m_mpq_lar_core_solver.m_r_solver.m_inf_set.m_index) { - lean_assert(m_mpq_lar_core_solver.m_r_heading[j] >= 0); - if (m_mpq_lar_core_solver.m_r_solver.column_is_feasible(j)) - became_feas.push_back(j); - } - for (unsigned j : became_feas) - m_mpq_lar_core_solver.m_r_solver.m_inf_set.erase(j); - if (use_tableau_costs()) { - for (unsigned j : became_feas) - m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); - for (unsigned j : basic_columns_with_changed_cost) - m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); - lean_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); - } - } - - - void shrink_explanation_to_minimum(vector> & explanation) const { - // implementing quickXplain - quick_xplain::run(explanation, *this); - lean_assert(this->explanation_is_correct(explanation)); + bool column_value_is_integer(unsigned j) const { + const impq & v = m_mpq_lar_core_solver.m_r_x[j]; + return v.is_int(); } + + bool column_is_real(unsigned j) const { + return !column_is_int(j); + } + + bool model_is_int_feasible() const; + + const impq & column_low_bound(unsigned j) const { + return m_mpq_lar_core_solver.low_bound(j); + } + + const impq & column_upper_bound(unsigned j) const { + return m_mpq_lar_core_solver.upper_bound(j); + } + + bool column_is_bounded(unsigned j) const { + return m_mpq_lar_core_solver.column_is_bounded(j); + } + + void get_bound_constraint_witnesses_for_column(unsigned j, constraint_index & lc, constraint_index & uc) const { + const ul_pair & ul = m_vars_to_ul_pairs[j]; + lc = ul.low_bound_witness(); + uc = ul.upper_bound_witness(); + } + indexed_vector & get_column_in_lu_mode(unsigned j) { + m_column_buffer.clear(); + m_column_buffer.resize(A_r().row_count()); + m_mpq_lar_core_solver.m_r_solver.solve_Bd(j, m_column_buffer); + return m_column_buffer; + } + + bool bound_is_integer_if_needed(unsigned j, const mpq & right_side) const; }; } diff --git a/src/util/lp/lar_solver_instances.cpp b/src/util/lp/lar_solver_instances.cpp new file mode 100644 index 000000000..98f59edb9 --- /dev/null +++ b/src/util/lp/lar_solver_instances.cpp @@ -0,0 +1,13 @@ +/* + Copyright (c) 2017 Microsoft Corporation + Author: Lev Nachmanson +*/ + +#include "util/lp/lar_solver.cpp" + +template void lean::lar_solver::copy_from_mpq_matrix(class lean::static_matrix &); + + + + + diff --git a/src/util/lp/lp_core_solver_base.h b/src/util/lp/lp_core_solver_base.h index a12b7b5d2..925206680 100644 --- a/src/util/lp/lp_core_solver_base.h +++ b/src/util/lp/lp_core_solver_base.h @@ -429,6 +429,7 @@ public: void init_lu(); int pivots_in_column_and_row_are_different(int entering, int leaving) const; void pivot_fixed_vars_from_basis(); + bool pivot_column_general(unsigned j, unsigned j_basic, indexed_vector & w); bool pivot_for_tableau_on_basis(); bool pivot_row_for_tableau_on_basis(unsigned row); void init_basic_part_of_basis_heading() { @@ -568,8 +569,8 @@ public: default: lean_assert(false); } - std::cout << "basis heading = " << m_basis_heading[j] << std::endl; - std::cout << "x = " << m_x[j] << std::endl; + out << "basis heading = " << m_basis_heading[j] << std::endl; + out << "x = " << m_x[j] << std::endl; /* std::cout << "cost = " << m_costs[j] << std::endl; std:: cout << "m_d = " << m_d[j] << std::endl;*/ diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp index a0dba9de7..d551daf27 100644 --- a/src/util/lp/lp_core_solver_base.hpp +++ b/src/util/lp/lp_core_solver_base.hpp @@ -923,7 +923,27 @@ template void lp_core_solver_base::transpose_row transpose_basis(i, j); m_A.transpose_rows(i, j); } - +// j is the new basic column, j_basic - the leaving column +template bool lp_core_solver_base::pivot_column_general(unsigned j, unsigned j_basic, indexed_vector & w) { + unsigned row_index = m_basis_heading[j_basic]; + change_basis(j, j_basic); + if (m_settings.m_simplex_strategy == simplex_strategy_enum::lu) { + if (m_factorization->need_to_refactor()) { + init_lu(); + } else { + m_factorization->prepare_entering(j, w); // to init vector w + m_factorization->replace_column(zero_of_type(), w, row_index); + } + if (m_factorization->get_status() != LU_status::OK) { + change_basis(j_basic, j); + init_lu(); + return false; + } + } else { // the tableau case + pivot_column_tableau(j, row_index); + } + return true; +} template void lp_core_solver_base::pivot_fixed_vars_from_basis() { // run over basis and non-basis at the same time indexed_vector w(m_basis.size()); // the buffer @@ -943,22 +963,9 @@ template void lp_core_solver_base::pivot_fixed_v if (j >= m_nbasis.size()) break; j++; - if (m_factorization->need_to_refactor()) { - change_basis(jj, ii); - init_lu(); - } else { - m_factorization->prepare_entering(jj, w); // to init vector w - m_factorization->replace_column(zero_of_type(), w, m_basis_heading[ii]); - change_basis(jj, ii); - } - if (m_factorization->get_status() != LU_status::OK) { - change_basis(ii, jj); - init_lu(); - } else { + if (!pivot_column_general(jj, ii, w)) break; - } - } - lean_assert(m_factorization->get_status()== LU_status::OK); + } } } diff --git a/src/util/lp/lp_settings.h b/src/util/lp/lp_settings.h index aac3692f9..736e4cda4 100644 --- a/src/util/lp/lp_settings.h +++ b/src/util/lp/lp_settings.h @@ -16,13 +16,16 @@ namespace lean { typedef unsigned var_index; typedef unsigned constraint_index; typedef unsigned row_index; + +typedef vector> explanation_t; + enum class column_type { free_column = 0, - low_bound = 1, - upper_bound = 2, - boxed = 3, - fixed = 4 - }; + low_bound = 1, + upper_bound = 2, + boxed = 3, + fixed = 4 +}; enum class simplex_strategy_enum { undecided = 3, @@ -75,11 +78,14 @@ public: }; struct stats { + unsigned m_make_feasible; unsigned m_total_iterations; unsigned m_iters_with_no_cost_growing; unsigned m_num_factorizations; unsigned m_num_of_implied_bounds; unsigned m_need_to_solve_inf; + unsigned m_max_cols; + unsigned m_max_rows; stats() { reset(); } void reset() { memset(this, 0, sizeof(*this)); } }; @@ -198,7 +204,8 @@ public: use_breakpoints_in_feasibility_search(false), max_row_length_for_bound_propagation(300), 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_threshold(10000000) {} void set_resource_limit(lp_resource_limit& lim) { m_resource_limit = &lim; } @@ -278,13 +285,13 @@ public: return m_simplex_strategy; } - bool use_lu() const { - return m_simplex_strategy == simplex_strategy_enum::lu; - } + bool use_lu() const { + return m_simplex_strategy == simplex_strategy_enum::lu; + } bool use_tableau() const { - return m_simplex_strategy == simplex_strategy_enum::tableau_rows || - m_simplex_strategy == simplex_strategy_enum::tableau_costs; + return m_simplex_strategy == simplex_strategy_enum::tableau_rows || + m_simplex_strategy == simplex_strategy_enum::tableau_costs; } bool use_tableau_rows() const { @@ -305,6 +312,7 @@ public: unsigned max_row_length_for_bound_propagation; bool backup_costs; unsigned column_number_threshold_for_using_lu_in_lar_solver; + unsigned m_int_branch_cut_threshold; }; // end of lp_settings class diff --git a/src/util/lp/lp_settings_instances.cpp b/src/util/lp/lp_settings_instances.cpp index e9a3888ba..ac2ed4b51 100644 --- a/src/util/lp/lp_settings_instances.cpp +++ b/src/util/lp/lp_settings_instances.cpp @@ -2,8 +2,8 @@ Copyright (c) 2017 Microsoft Corporation Author: Lev Nachmanson */ -#include "util/vector.h" #include +#include "util/vector.h" #include "util/lp/lp_settings.hpp" template bool lean::vectors_are_equal(vector const&, vector const&); template bool lean::vectors_are_equal(vector const&, vector const&); diff --git a/src/util/lp/mps_reader.h b/src/util/lp/mps_reader.h index 4c793d56e..eb83735ca 100644 --- a/src/util/lp/mps_reader.h +++ b/src/util/lp/mps_reader.h @@ -810,7 +810,7 @@ public: auto kind = get_lar_relation_from_row(row->m_type); vector> ls; for (auto s : row->m_row_columns) { - var_index i = solver->add_var(get_var_index(s.first)); + var_index i = solver->add_var(get_var_index(s.first), false); ls.push_back(std::make_pair(s.second, i)); } solver->add_constraint(ls, kind, row->m_right_side); @@ -828,20 +828,20 @@ public: void create_low_constraint_for_var(column* col, bound * b, lar_solver *solver) { vector> ls; - var_index i = solver->add_var(col->m_index); + var_index i = solver->add_var(col->m_index, false); ls.push_back(std::make_pair(numeric_traits::one(), i)); solver->add_constraint(ls, GE, b->m_low); } void create_upper_constraint_for_var(column* col, bound * b, lar_solver *solver) { - var_index i = solver->add_var(col->m_index); + var_index i = solver->add_var(col->m_index, false); vector> ls; ls.push_back(std::make_pair(numeric_traits::one(), i)); solver->add_constraint(ls, LE, b->m_upper); } void create_equality_contraint_for_var(column* col, bound * b, lar_solver *solver) { - var_index i = solver->add_var(col->m_index); + var_index i = solver->add_var(col->m_index, false); vector> ls; ls.push_back(std::make_pair(numeric_traits::one(), i)); solver->add_constraint(ls, EQ, b->m_fixed_value); @@ -850,7 +850,7 @@ public: void fill_lar_solver_on_columns(lar_solver * solver) { for (auto s : m_columns) { mps_reader::column * col = s.second; - solver->add_var(col->m_index); + solver->add_var(col->m_index, false); auto b = col->m_bound; if (b == nullptr) return; diff --git a/src/util/lp/nra_solver.cpp b/src/util/lp/nra_solver.cpp new file mode 100644 index 000000000..81372be32 --- /dev/null +++ b/src/util/lp/nra_solver.cpp @@ -0,0 +1,264 @@ +/* + Copyright (c) 2017 Microsoft Corporation + Author: Lev Nachmanson +*/ + +#include "util/lp/lar_solver.h" +#include "util/lp/nra_solver.h" +#include "nlsat/nlsat_solver.h" +#include "math/polynomial/polynomial.h" +#include "math/polynomial/algebraic_numbers.h" +#include "util/map.h" + + +namespace nra { + + struct mon_eq { + mon_eq(lean::var_index v, unsigned sz, lean::var_index const* vs): + m_v(v), m_vs(sz, vs) {} + lean::var_index m_v; + svector m_vs; + }; + + struct solver::imp { + lean::lar_solver& s; + reslimit& m_limit; + params_ref m_params; + u_map m_lp2nl; // map from lar_solver variables to nlsat::solver variables + scoped_ptr m_nlsat; + vector m_monomials; + unsigned_vector m_monomials_lim; + mutable std::unordered_map m_variable_values; // current model + + imp(lean::lar_solver& s, reslimit& lim, params_ref const& p): + s(s), + m_limit(lim), + m_params(p) { + } + + bool need_check() { + return !m_monomials.empty() && !check_assignments(); + } + + void add(lean::var_index v, unsigned sz, lean::var_index const* vs) { + m_monomials.push_back(mon_eq(v, sz, vs)); + } + + void push() { + m_monomials_lim.push_back(m_monomials.size()); + } + + void pop(unsigned n) { + if (n == 0) return; + m_monomials.shrink(m_monomials_lim[m_monomials_lim.size() - n]); + m_monomials_lim.shrink(m_monomials_lim.size() - n); + } + + /* + \brief Check if polynomials are well defined. + multiply values for vs and check if they are equal to value for v. + epsilon has been computed. + */ + bool check_assignment(mon_eq const& m) const { + rational r1 = m_variable_values[m.m_v]; + rational r2(1); + for (auto w : m.m_vs) { + r2 *= m_variable_values[w]; + } + return r1 == r2; + } + + bool check_assignments() const { + s.get_model(m_variable_values); + for (auto const& m : m_monomials) { + if (!check_assignment(m)) return false; + } + return true; + } + + /** + \brief one-shot nlsat check. + A one shot checker is the least functionality that can + enable non-linear reasoning. + In addition to checking satisfiability we would also need + to identify equalities in the model that should be assumed + with the remaining solver. + + TBD: use partial model from lra_solver to prime the state of nlsat_solver. + TBD: explore more incremental ways of applying nlsat (using assumptions) + */ + lbool check(lean::explanation_t& ex) { + SASSERT(need_check()); + m_nlsat = alloc(nlsat::solver, m_limit, m_params); + m_lp2nl.reset(); + vector core; + + // add linear inequalities from lra_solver + for (unsigned i = 0; i < s.constraint_count(); ++i) { + add_constraint(i); + } + + // add polynomial definitions. + for (auto const& m : m_monomials) { + add_monomial_eq(m); + } + // TBD: add variable bounds? + + lbool r = m_nlsat->check(); + TRACE("arith", m_nlsat->display(tout << r << "\n");); + switch (r) { + case l_true: + break; + case l_false: + ex.reset(); + m_nlsat->get_core(core); + for (auto c : core) { + unsigned idx = static_cast(static_cast(c) - this); + ex.push_back(std::pair(rational(1), idx)); + TRACE("arith", tout << "ex: " << idx << "\n";); + } + break; + + case l_undef: + break; + } + return r; + } + + void add_monomial_eq(mon_eq const& m) { + polynomial::manager& pm = m_nlsat->pm(); + svector vars; + for (auto v : m.m_vs) { + vars.push_back(lp2nl(v)); + } + polynomial::monomial_ref m1(pm.mk_monomial(vars.size(), vars.c_ptr()), pm); + polynomial::monomial_ref m2(pm.mk_monomial(lp2nl(m.m_v), 1), pm); + polynomial::monomial* mls[2] = { m1, m2 }; + polynomial::scoped_numeral_vector coeffs(pm.m()); + coeffs.push_back(mpz(1)); + coeffs.push_back(mpz(-1)); + polynomial::polynomial_ref p(pm.mk_polynomial(2, coeffs.c_ptr(), mls), pm); + polynomial::polynomial* ps[1] = { p }; + bool even[1] = { false }; + nlsat::literal lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, even); + m_nlsat->mk_clause(1, &lit, 0); + } + + void add_constraint(unsigned idx) { + auto& c = s.get_constraint(idx); + auto& pm = m_nlsat->pm(); + auto k = c.m_kind; + auto rhs = c.m_right_side; + auto lhs = c.get_left_side_coefficients(); + auto sz = lhs.size(); + svector vars; + rational den = denominator(rhs); + for (auto kv : lhs) { + vars.push_back(lp2nl(kv.second)); + den = lcm(den, denominator(kv.first)); + } + vector coeffs; + for (auto kv : lhs) { + coeffs.push_back(den * kv.first); + } + rhs *= den; + polynomial::polynomial_ref p(pm.mk_linear(sz, coeffs.c_ptr(), vars.c_ptr(), -rhs), pm); + polynomial::polynomial* ps[1] = { p }; + bool is_even[1] = { false }; + nlsat::literal lit; + nlsat::assumption a = this + idx; + switch (k) { + case lean::lconstraint_kind::LE: + lit = ~m_nlsat->mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even); + break; + case lean::lconstraint_kind::GE: + lit = ~m_nlsat->mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even); + break; + case lean::lconstraint_kind::LT: + lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even); + break; + case lean::lconstraint_kind::GT: + lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even); + break; + case lean::lconstraint_kind::EQ: + lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, is_even); + break; + } + m_nlsat->mk_clause(1, &lit, a); + } + + bool is_int(lean::var_index v) { + return s.var_is_int(v); + } + + + polynomial::var lp2nl(lean::var_index v) { + polynomial::var r; + if (!m_lp2nl.find(v, r)) { + r = m_nlsat->mk_var(is_int(v)); + m_lp2nl.insert(v, r); + } + return r; + } + + nlsat::anum const& value(lean::var_index v) const { + return m_nlsat->value(m_lp2nl.find(v)); + } + + nlsat::anum_manager& am() { + return m_nlsat->am(); + } + + std::ostream& display(std::ostream& out) const { + for (auto m : m_monomials) { + out << "v" << m.m_v << " = "; + for (auto v : m.m_vs) { + out << "v" << v << " "; + } + out << "\n"; + } + return out; + } + }; + + solver::solver(lean::lar_solver& s, reslimit& lim, params_ref const& p) { + m_imp = alloc(imp, s, lim, p); + } + + solver::~solver() { + dealloc(m_imp); + } + + void solver::add_monomial(lean::var_index v, unsigned sz, lean::var_index const* vs) { + m_imp->add(v, sz, vs); + } + + lbool solver::check(lean::explanation_t& ex) { + return m_imp->check(ex); + } + + bool solver::need_check() { + return m_imp->need_check(); + } + + void solver::push() { + m_imp->push(); + } + + void solver::pop(unsigned n) { + m_imp->pop(n); + } + + std::ostream& solver::display(std::ostream& out) const { + return m_imp->display(out); + } + + nlsat::anum const& solver::value(lean::var_index v) const { + return m_imp->value(v); + } + + nlsat::anum_manager& solver::am() { + return m_imp->am(); + } + +} diff --git a/src/util/lp/nra_solver.h b/src/util/lp/nra_solver.h new file mode 100644 index 000000000..0b02e7136 --- /dev/null +++ b/src/util/lp/nra_solver.h @@ -0,0 +1,70 @@ +/* + Copyright (c) 2017 Microsoft Corporation + Author: Lev Nachmanson +*/ + +#pragma once +#include "util/vector.h" +#include "util/lp/lp_settings.h" +#include "util/rlimit.h" +#include "util/params.h" +#include "nlsat/nlsat_solver.h" + +namespace lean { + class lar_solver; +} + + +namespace nra { + + + + class solver { + struct imp; + imp* m_imp; + + public: + + solver(lean::lar_solver& s, reslimit& lim, params_ref const& p = params_ref()); + + ~solver(); + + /* + \brief Add a definition v = vs[0]*vs[1]*...*vs[sz-1] + The variable v is equal to the product of variables vs. + */ + void add_monomial(lean::var_index v, unsigned sz, lean::var_index const* vs); + + /* + \brief Check feasiblity of linear constraints augmented by polynomial definitions + that are added. + */ + lbool check(lean::explanation_t& ex); + + /* + \brief determine whether nra check is needed. + */ + bool need_check(); + + /* + \brief Access model. + */ + nlsat::anum const& value(lean::var_index v) const; + + nlsat::anum_manager& am(); + + /* + \brief push and pop scope. + Monomial definitions are retraced when popping scope. + */ + void push(); + + void pop(unsigned n); + + /* + \brief display state + */ + std::ostream& display(std::ostream& out) const; + + }; +} diff --git a/src/util/lp/numeric_pair.h b/src/util/lp/numeric_pair.h index 84c99b3b1..db7b71119 100644 --- a/src/util/lp/numeric_pair.h +++ b/src/util/lp/numeric_pair.h @@ -199,6 +199,11 @@ struct numeric_pair { std::string to_string() const { return std::string("(") + T_to_string(x) + ", " + T_to_string(y) + ")"; } + + bool is_int() const { + return x.is_int() && y.is_zero(); + } + }; @@ -324,4 +329,26 @@ struct convert_struct { template bool is_epsilon_small(const X & v, const double &eps) { return convert_struct::is_epsilon_small(v, eps);} template bool below_bound_numeric(const X & x, const X & bound, const double& eps) { return convert_struct::below_bound_numeric(x, bound, eps);} template bool above_bound_numeric(const X & x, const X & bound, const double& eps) { return convert_struct::above_bound_numeric(x, bound, eps);} +template T floor(const numeric_pair & r) { + if (r.x.is_int()) { + if (r.y.is_nonneg()) { + return r.x; + } + return r.x - mpq::one(); + } + + return floor(r.x); +} + +template T ceil(const numeric_pair & r) { + if (r.x.is_int()) { + if (r.y.is_nonpos()) { + return r.x; + } + return r.x + mpq::one(); + } + + return ceil(r.x); +} + } diff --git a/src/util/lp/quick_xplain.cpp b/src/util/lp/quick_xplain.cpp index a4b6fb0e6..df409240e 100644 --- a/src/util/lp/quick_xplain.cpp +++ b/src/util/lp/quick_xplain.cpp @@ -20,7 +20,7 @@ void quick_xplain::copy_constraint_and_add_constraint_vars(const lar_constraint& vector < std::pair> ls; for (auto & p : lar_c.get_left_side_coefficients()) { unsigned j = p.second; - unsigned lj = m_qsol.add_var(j); + unsigned lj = m_qsol.add_var(j, false); ls.push_back(std::make_pair(p.first, lj)); } m_constraints_in_local_vars.push_back(lar_constraint(ls, lar_c.m_kind, lar_c.m_right_side)); @@ -94,7 +94,7 @@ bool quick_xplain::is_feasible(const vector & x, unsigned k) const { vector < std::pair> ls; const lar_constraint & c = m_constraints_in_local_vars[i]; for (auto & p : c.get_left_side_coefficients()) { - unsigned lj = l.add_var(p.second); + unsigned lj = l.add_var(p.second, false); ls.push_back(std::make_pair(p.first, lj)); } l.add_constraint(ls, c.m_kind, c.m_right_side); diff --git a/src/util/lp/stacked_vector.h b/src/util/lp/stacked_vector.h index 3f39dd346..14b0d0141 100644 --- a/src/util/lp/stacked_vector.h +++ b/src/util/lp/stacked_vector.h @@ -32,7 +32,10 @@ public: operator const B&() const { return m_vec.m_vector[m_i]; } - + + bool operator==(B const& other) const { + return m_vec.m_vector[m_i] == other; + } }; class ref_const { diff --git a/src/util/lp/static_matrix_instances.cpp b/src/util/lp/static_matrix_instances.cpp index d0e2045c0..59905929e 100644 --- a/src/util/lp/static_matrix_instances.cpp +++ b/src/util/lp/static_matrix_instances.cpp @@ -2,8 +2,8 @@ Copyright (c) 2017 Microsoft Corporation Author: Lev Nachmanson */ -#include "util/vector.h" #include +#include "util/vector.h" #include #include #include "util/lp/static_matrix.hpp" From c44c8284bd21472d66dc04c56cc99b83bb10e88e Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 30 Jun 2017 18:10:36 -0700 Subject: [PATCH 097/159] use worklist algorithm to avoid stack overflow #1125 Signed-off-by: Nikolaj Bjorner --- src/smt/theory_seq.cpp | 116 ++++++++++++++++++++++++++++------------- src/smt/theory_seq.h | 3 ++ 2 files changed, 83 insertions(+), 36 deletions(-) diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index 4dfff21c2..1c293ad8d 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -2863,77 +2863,121 @@ bool theory_seq::canonize(expr_ref_vector const& es, expr_ref_vector& result, de return change; } - -expr_ref theory_seq::expand(expr* e0, dependency*& eqs) { +expr_ref theory_seq::expand(expr* e, dependency*& eqs) { + unsigned sz = m_expand_todo.size(); + m_expand_todo.push_back(e); + expr_ref result(m); + while (m_expand_todo.size() != sz) { + expr* e = m_expand_todo.back(); + result = expand1(e, eqs); + if (result.get()) m_expand_todo.pop_back(); + } + return result; +} + +expr_ref theory_seq::try_expand(expr* e, dependency*& eqs){ expr_ref result(m); - dependency* deps = 0; expr_dep ed; - if (m_rep.find_cache(e0, ed)) { + if (m_rep.find_cache(e, ed)) { eqs = m_dm.mk_join(eqs, ed.second); result = ed.first; - return result; } + else { + m_expand_todo.push_back(e); + } + return result; +} +expr_ref theory_seq::expand1(expr* e0, dependency*& eqs) { + expr_ref result(m); + dependency* deps = 0; + result = try_expand(e0, deps); + if (result) return result; expr* e = m_rep.find(e0, deps); expr* e1, *e2, *e3; + expr_ref arg1(m), arg2(m); context& ctx = get_context(); if (m_util.str.is_concat(e, e1, e2)) { - result = mk_concat(expand(e1, deps), expand(e2, deps)); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = mk_concat(arg1, arg2); } else if (m_util.str.is_empty(e) || m_util.str.is_string(e)) { result = e; } else if (m_util.str.is_prefix(e, e1, e2)) { - result = m_util.str.mk_prefix(expand(e1, deps), expand(e2, deps)); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = m_util.str.mk_prefix(arg1, arg2); } else if (m_util.str.is_suffix(e, e1, e2)) { - result = m_util.str.mk_suffix(expand(e1, deps), expand(e2, deps)); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = m_util.str.mk_suffix(arg1, arg2); } else if (m_util.str.is_contains(e, e1, e2)) { - result = m_util.str.mk_contains(expand(e1, deps), expand(e2, deps)); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = m_util.str.mk_contains(arg1, arg2); } else if (m_util.str.is_unit(e, e1)) { - result = m_util.str.mk_unit(expand(e1, deps)); + arg1 = try_expand(e1, deps); + if (!arg1) return result; + result = m_util.str.mk_unit(arg1); } else if (m_util.str.is_index(e, e1, e2)) { - result = m_util.str.mk_index(expand(e1, deps), expand(e2, deps), m_autil.mk_int(0)); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = m_util.str.mk_index(arg1, arg2, m_autil.mk_int(0)); } else if (m_util.str.is_index(e, e1, e2, e3)) { - result = m_util.str.mk_index(expand(e1, deps), expand(e2, deps), e3); + arg1 = try_expand(e1, deps); + arg2 = try_expand(e2, deps); + if (!arg1 || !arg2) return result; + result = m_util.str.mk_index(arg1, arg2, e3); } else if (m.is_ite(e, e1, e2, e3)) { if (ctx.e_internalized(e) && ctx.e_internalized(e2) && ctx.get_enode(e)->get_root() == ctx.get_enode(e2)->get_root()) { - result = expand(e2, deps); + result = try_expand(e2, deps); + if (!result) return result; add_dependency(deps, ctx.get_enode(e), ctx.get_enode(e2)); } else if (ctx.e_internalized(e) && ctx.e_internalized(e2) && ctx.get_enode(e)->get_root() == ctx.get_enode(e3)->get_root()) { - result = expand(e3, deps); + result = try_expand(e3, deps); + if (!result) return result; add_dependency(deps, ctx.get_enode(e), ctx.get_enode(e3)); } else { - literal lit(mk_literal(e1)); + literal lit(mk_literal(e1)); #if 0 - expr_ref sk_ite = mk_sk_ite(e1, e2, e3); - add_axiom(~lit, mk_eq(e2, sk_ite, false)); - add_axiom( lit, mk_eq(e3, sk_ite, false)); - result = sk_ite; - + expr_ref sk_ite = mk_sk_ite(e1, e2, e3); + add_axiom(~lit, mk_eq(e2, sk_ite, false)); + add_axiom( lit, mk_eq(e3, sk_ite, false)); + result = sk_ite; + #else - switch (ctx.get_assignment(lit)) { - case l_true: - deps = m_dm.mk_join(deps, m_dm.mk_leaf(assumption(lit))); - result = expand(e2, deps); - break; - case l_false: - deps = m_dm.mk_join(deps, m_dm.mk_leaf(assumption(~lit))); - result = expand(e3, deps); - break; - case l_undef: - result = e; - m_reset_cache = true; - TRACE("seq", tout << "undef: " << result << "\n"; - tout << lit << "@ level: " << ctx.get_scope_level() << "\n";); - break; - } + switch (ctx.get_assignment(lit)) { + case l_true: + deps = m_dm.mk_join(deps, m_dm.mk_leaf(assumption(lit))); + result = try_expand(e2, deps); + if (!result) return result; + break; + case l_false: + deps = m_dm.mk_join(deps, m_dm.mk_leaf(assumption(~lit))); + result = try_expand(e3, deps); + if (!result) return result; + break; + case l_undef: + result = e; + m_reset_cache = true; + TRACE("seq", tout << "undef: " << result << "\n"; + tout << lit << "@ level: " << ctx.get_scope_level() << "\n";); + break; + } #endif } } diff --git a/src/smt/theory_seq.h b/src/smt/theory_seq.h index 5fd31e2ca..f7212e608 100644 --- a/src/smt/theory_seq.h +++ b/src/smt/theory_seq.h @@ -462,7 +462,10 @@ namespace smt { expr_ref canonize(expr* e, dependency*& eqs); bool canonize(expr* e, expr_ref_vector& es, dependency*& eqs); bool canonize(expr_ref_vector const& es, expr_ref_vector& result, dependency*& eqs); + ptr_vector m_expand_todo; expr_ref expand(expr* e, dependency*& eqs); + expr_ref expand1(expr* e, dependency*& eqs); + expr_ref try_expand(expr* e, dependency*& eqs); void add_dependency(dependency*& dep, enode* a, enode* b); void get_concat(expr* e, ptr_vector& concats); From be4b0ffe69282f52faaf23cf4ed1a239c25d1118 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 30 Jun 2017 19:36:38 -0700 Subject: [PATCH 098/159] fix unsoundness bug instroduced when fixing #1125 Signed-off-by: Nikolaj Bjorner --- src/smt/theory_seq.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index 1c293ad8d..ea53f1342 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -2879,7 +2879,9 @@ expr_ref theory_seq::try_expand(expr* e, dependency*& eqs){ expr_ref result(m); expr_dep ed; if (m_rep.find_cache(e, ed)) { - eqs = m_dm.mk_join(eqs, ed.second); + if (e != ed.first) { + eqs = m_dm.mk_join(eqs, ed.second); + } result = ed.first; } else { @@ -2889,9 +2891,9 @@ expr_ref theory_seq::try_expand(expr* e, dependency*& eqs){ } expr_ref theory_seq::expand1(expr* e0, dependency*& eqs) { expr_ref result(m); - dependency* deps = 0; - result = try_expand(e0, deps); + result = try_expand(e0, eqs); if (result) return result; + dependency* deps = 0; expr* e = m_rep.find(e0, deps); expr* e1, *e2, *e3; expr_ref arg1(m), arg2(m); From 8310fed528622a3a91f65d223e2165b6a46dc234 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Sun, 25 Jun 2017 22:36:03 +0100 Subject: [PATCH 099/159] [TravisCI] Implement TravisCI build and testing infrastructure for Linux The Linux builds rely on Docker (using Ubuntu 16.04LTS and Ubuntu 14.04LTS) to build and test Z3 so that builds are easily reproducible. A build status button has been added to `README.md` so that it is easy to see the current build status. More documentation can be found in `contrib/ci/README.md`. This implementation currently tests 13 different configurations. If build times become too long we can remove some of them. Although it would be nice to test macOS builds that requires significantly more work so I have left this as future work. --- .dockerignore | 4 + .travis.yml | 68 ++++++ README.md | 6 +- .../z3_base_ubuntu32_16.04.Dockerfile | 50 +++++ .../z3_base_ubuntu_14.04.Dockerfile | 35 +++ .../z3_base_ubuntu_16.04.Dockerfile | 38 ++++ contrib/ci/Dockerfiles/z3_build.Dockerfile | 109 +++++++++ contrib/ci/README.md | 113 ++++++++++ contrib/ci/maintainers.txt | 3 + contrib/ci/scripts/build_z3_cmake.sh | 128 +++++++++++ contrib/ci/scripts/run_quiet.sh | 41 ++++ contrib/ci/scripts/set_compiler_flags.sh | 46 ++++ contrib/ci/scripts/set_generator_args.sh | 20 ++ contrib/ci/scripts/test_z3_docs.sh | 24 ++ contrib/ci/scripts/test_z3_examples_cmake.sh | 87 ++++++++ contrib/ci/scripts/test_z3_install_cmake.sh | 24 ++ contrib/ci/scripts/test_z3_system_tests.sh | 54 +++++ .../ci/scripts/test_z3_unit_tests_cmake.sh | 24 ++ contrib/ci/scripts/travis_ci_entry_point.sh | 18 ++ .../ci/scripts/travis_ci_linux_entry_point.sh | 208 ++++++++++++++++++ .../ci/scripts/travis_ci_osx_entry_point.sh | 10 + 21 files changed, 1107 insertions(+), 3 deletions(-) create mode 100644 .dockerignore create mode 100644 .travis.yml create mode 100644 contrib/ci/Dockerfiles/z3_base_ubuntu32_16.04.Dockerfile create mode 100644 contrib/ci/Dockerfiles/z3_base_ubuntu_14.04.Dockerfile create mode 100644 contrib/ci/Dockerfiles/z3_base_ubuntu_16.04.Dockerfile create mode 100644 contrib/ci/Dockerfiles/z3_build.Dockerfile create mode 100644 contrib/ci/README.md create mode 100644 contrib/ci/maintainers.txt create mode 100755 contrib/ci/scripts/build_z3_cmake.sh create mode 100644 contrib/ci/scripts/run_quiet.sh create mode 100644 contrib/ci/scripts/set_compiler_flags.sh create mode 100644 contrib/ci/scripts/set_generator_args.sh create mode 100755 contrib/ci/scripts/test_z3_docs.sh create mode 100755 contrib/ci/scripts/test_z3_examples_cmake.sh create mode 100755 contrib/ci/scripts/test_z3_install_cmake.sh create mode 100755 contrib/ci/scripts/test_z3_system_tests.sh create mode 100755 contrib/ci/scripts/test_z3_unit_tests_cmake.sh create mode 100755 contrib/ci/scripts/travis_ci_entry_point.sh create mode 100755 contrib/ci/scripts/travis_ci_linux_entry_point.sh create mode 100755 contrib/ci/scripts/travis_ci_osx_entry_point.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..e85dae524 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +**/*.swp +**/*.pyc +.git +**/*.Dockerfile diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..e8e207466 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,68 @@ +cache: + # This persistent cache is used to cache the building of + # docker base images. + directories: + - $DOCKER_TRAVIS_CI_CACHE_DIR +sudo: required +language: cpp +services: + - docker +env: + global: + # This environment variable tells the `travis_ci_linux_entry_point.sh` + # script to look for a cached Docker image. + - DOCKER_TRAVIS_CI_CACHE_DIR=$HOME/.cache/docker + # Configurations + matrix: +############################################################################### +# Ubuntu 16.04 LTS +############################################################################### + # 64-bit GCC 5.4 RelWithDebInfo + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo + # 64-bit Clang 3.9 RelWithDebInfo + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo + + # 64-bit GCC 5.4 Debug + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug + # 64-bit Clang Debug + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug + + # 32-bit GCC 5.4 RelWithDebInfo + - LINUX_BASE=ubuntu32_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=i686 Z3_BUILD_TYPE=RelWithDebInfo + + # Both of the two configurations below build the docs because the current + # implementation uses python as part of the building process. + # TODO: Teach one of the configurations to upload built docs somewhere. + # Test with Python 3 and API docs + - LINUX_BASE=ubuntu_16.04 PYTHON_EXECUTABLE=/usr/bin/python3 BUILD_DOCS=1 + # Test with LibGMP and API docs + - LINUX_BASE=ubuntu_16.04 TARGET_ARCH=x86_64 USE_LIBGMP=1 BUILD_DOCS=1 PYTHON_EXECUTABLE=/usr/bin/python2.7 + + # Test without OpenMP + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo USE_OPENMP=0 + + # Unix Makefile generator build + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_CMAKE_GENERATOR="Unix Makefiles" + + # LTO build + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 USE_LTO=1 + + # Static build. Note we have disable building the bindings because they won't work with a static libz3 + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_STATIC_BUILD=1 DOTNET_BINDINGS=0 JAVA_BINDINGS=0 PYTHON_BINDINGS=0 + +############################################################################### +# Ubuntu 14.04 LTS +############################################################################### + # GCC 4.8 + # 64-bit GCC 4.8 RelWithDebInfo + - LINUX_BASE=ubuntu_14.04 C_COMPILER=/usr/bin/gcc-4.8 CXX_COMPILER=/usr/bin/g++-4.8 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo + # 64-bit GCC 4.8 Debug + - LINUX_BASE=ubuntu_14.04 C_COMPILER=/usr/bin/gcc-4.8 CXX_COMPILER=/usr/bin/g++-4.8 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug + +# TODO: OSX support +#matrix: +# include: +# - os: osx +# osx_image: xcode 8.2 +script: + - contrib/ci/scripts/travis_ci_entry_point.sh diff --git a/README.md b/README.md index f92a5389a..465348dbd 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z ## Build status -| Windows x86 | Windows x64 | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | -| ----------- | ----------- | ---------- | ---------- | ---------- | --- | -![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | ![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge) +| Windows x86 | Windows x64 | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | TravisCI | +| ----------- | ----------- | ---------- | ---------- | ---------- | --- | -------- | +![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | ![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) [1]: #building-z3-on-windows-using-visual-studio-command-prompt [2]: #building-z3-using-make-and-gccclang diff --git a/contrib/ci/Dockerfiles/z3_base_ubuntu32_16.04.Dockerfile b/contrib/ci/Dockerfiles/z3_base_ubuntu32_16.04.Dockerfile new file mode 100644 index 000000000..d8a32edea --- /dev/null +++ b/contrib/ci/Dockerfiles/z3_base_ubuntu32_16.04.Dockerfile @@ -0,0 +1,50 @@ +# This base image is not officially supported by Docker it +# is generated by running +# ``` +# ./update.sh xenial +# ``` +# from git@github.com:daald/docker-brew-ubuntu-core-32bit.git +# at commit 34ea593b40b423755b7d46b6c8c89fc8162ea74b +# +# We could actually store the image generated by this Dockerfile +# rather than just the bare image. However given we have a TravisCI +# cache I'm not sure if it faster to use the TravisCI cache or to +# download from DockerHub everytime. +FROM z3prover/ubuntu32:16.04 + +RUN apt-get update && \ + apt-get -y --no-install-recommends install \ + binutils \ + clang \ + clang-3.9 \ + cmake \ + doxygen \ + default-jdk \ + gcc \ + gcc-5 \ + git \ + graphviz \ + g++ \ + g++ \ + libgmp-dev \ + libgomp1 \ + libomp5 \ + libomp-dev \ + make \ + mono-devel \ + ninja-build \ + python3 \ + python3-setuptools \ + python2.7 \ + python-setuptools \ + sudo + +# Create `user` user for container with password `user`. and give it +# password-less sudo access +RUN useradd -m user && \ + echo user:user | chpasswd && \ + cp /etc/sudoers /etc/sudoers.bak && \ + echo 'user ALL=(root) NOPASSWD: ALL' >> /etc/sudoers +USER user +WORKDIR /home/user + diff --git a/contrib/ci/Dockerfiles/z3_base_ubuntu_14.04.Dockerfile b/contrib/ci/Dockerfiles/z3_base_ubuntu_14.04.Dockerfile new file mode 100644 index 000000000..c28e59e97 --- /dev/null +++ b/contrib/ci/Dockerfiles/z3_base_ubuntu_14.04.Dockerfile @@ -0,0 +1,35 @@ +FROM ubuntu:14.04 + +RUN apt-get update && \ + apt-get -y --no-install-recommends install \ + binutils \ + clang-3.9 \ + cmake \ + doxygen \ + default-jdk \ + gcc-multilib \ + gcc-4.8-multilib \ + git \ + graphviz \ + g++-multilib \ + g++-4.8-multilib \ + libgmp-dev \ + libgomp1 \ + lib32gomp1 \ + make \ + mono-devel \ + ninja-build \ + python3 \ + python3-setuptools \ + python2.7 \ + python-setuptools + +# Create `user` user for container with password `user`. and give it +# password-less sudo access +RUN useradd -m user && \ + echo user:user | chpasswd && \ + cp /etc/sudoers /etc/sudoers.bak && \ + echo 'user ALL=(root) NOPASSWD: ALL' >> /etc/sudoers +USER user +WORKDIR /home/user + diff --git a/contrib/ci/Dockerfiles/z3_base_ubuntu_16.04.Dockerfile b/contrib/ci/Dockerfiles/z3_base_ubuntu_16.04.Dockerfile new file mode 100644 index 000000000..98a5a3e09 --- /dev/null +++ b/contrib/ci/Dockerfiles/z3_base_ubuntu_16.04.Dockerfile @@ -0,0 +1,38 @@ +FROM ubuntu:16.04 + +RUN apt-get update && \ + apt-get -y --no-install-recommends install \ + binutils \ + clang \ + clang-3.9 \ + cmake \ + doxygen \ + default-jdk \ + gcc-multilib \ + gcc-5-multilib \ + git \ + graphviz \ + g++-multilib \ + g++-5-multilib \ + libgmp-dev \ + libgomp1 \ + libomp5 \ + libomp-dev \ + make \ + mono-devel \ + ninja-build \ + python3 \ + python3-setuptools \ + python2.7 \ + python-setuptools \ + sudo + +# Create `user` user for container with password `user`. and give it +# password-less sudo access +RUN useradd -m user && \ + echo user:user | chpasswd && \ + cp /etc/sudoers /etc/sudoers.bak && \ + echo 'user ALL=(root) NOPASSWD: ALL' >> /etc/sudoers +USER user +WORKDIR /home/user + diff --git a/contrib/ci/Dockerfiles/z3_build.Dockerfile b/contrib/ci/Dockerfiles/z3_build.Dockerfile new file mode 100644 index 000000000..8b922edff --- /dev/null +++ b/contrib/ci/Dockerfiles/z3_build.Dockerfile @@ -0,0 +1,109 @@ +ARG DOCKER_IMAGE_BASE +FROM ${DOCKER_IMAGE_BASE} + + +# Specify defaults. This can be changed when invoking +# `docker build`. +ARG ASAN_BUILD=0 +ARG BUILD_DOCS=0 +ARG CC=gcc +ARG CXX=g++ +ARG DOTNET_BINDINGS=1 +ARG JAVA_BINDINGS=1 +ARG NO_SUPPRESS_OUTPUT=0 +ARG PYTHON_BINDINGS=1 +ARG PYTHON_EXECUTABLE=/usr/bin/python2.7 +ARG RUN_SYSTEM_TESTS=1 +ARG RUN_UNIT_TESTS=1 +ARG TARGET_ARCH=x86_64 +ARG TEST_INSTALL=1 +ARG UBSAN_BUILD=0 +ARG USE_LIBGMP=0 +ARG USE_LTO=0 +ARG USE_OPENMP=1 +ARG Z3_SRC_DIR=/home/user/z3_src +ARG Z3_BUILD_TYPE=RelWithDebInfo +ARG Z3_CMAKE_GENERATOR=Ninja +ARG Z3_INSTALL_PREFIX=/usr +ARG Z3_STATIC_BUILD=0 +# Blank default indicates use latest. +ARG Z3_SYSTEM_TEST_GIT_REVISION +ARG Z3_VERBOSE_BUILD_OUTPUT=0 + +ENV \ + ASAN_BUILD=${ASAN_BUILD} \ + BUILD_DOCS=${BUILD_DOCS} \ + CC=${CC} \ + CXX=${CXX} \ + DOTNET_BINDINGS=${DOTNET_BINDINGS} \ + JAVA_BINDINGS=${JAVA_BINDINGS} \ + NO_SUPPRESS_OUTPUT=${NO_SUPPRESS_OUTPUT} \ + PYTHON_BINDINGS=${PYTHON_BINDINGS} \ + PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} \ + RUN_SYSTEM_TESTS=${RUN_SYSTEM_TESTS} \ + RUN_UNIT_TESTS=${RUN_UNIT_TESTS} \ + TARGET_ARCH=${TARGET_ARCH} \ + TEST_INSTALL=${TEST_INSTALL} \ + UBSAN_BUILD=${UBSAN_BUILD} \ + USE_LIBGMP=${USE_LIBGMP} \ + USE_LTO=${USE_LTO} \ + USE_OPENMP=${USE_OPENMP} \ + Z3_SRC_DIR=${Z3_SRC_DIR} \ + Z3_BUILD_DIR=/home/user/z3_build \ + Z3_CMAKE_GENERATOR=${Z3_CMAKE_GENERATOR} \ + Z3_VERBOSE_BUILD_OUTPUT=${Z3_VERBOSE_BUILD_OUTPUT} \ + Z3_STATIC_BUILD=${Z3_STATIC_BUILD} \ + Z3_SYSTEM_TEST_DIR=/home/user/z3_system_test \ + Z3_SYSTEM_TEST_GIT_REVISION=${Z3_SYSTEM_TEST_GIT_REVISION} \ + Z3_INSTALL_PREFIX=${Z3_INSTALL_PREFIX} + +# We add context across incrementally to maximal cache reuse + +# Build Z3 +RUN mkdir -p "${Z3_SRC_DIR}" && \ + mkdir -p "${Z3_SRC_DIR}/contrib/ci/scripts" +# Deliberately leave out `contrib` +ADD /cmake ${Z3_SRC_DIR}/cmake/ +ADD /doc ${Z3_SRC_DIR}/doc/ +ADD /examples ${Z3_SRC_DIR}/examples/ +ADD /scripts ${Z3_SRC_DIR}/scripts/ +ADD /src ${Z3_SRC_DIR}/src/ +ADD *.txt *.md RELEASE_NOTES ${Z3_SRC_DIR}/ + +ADD \ + /contrib/ci/scripts/build_z3_cmake.sh \ + /contrib/ci/scripts/set_compiler_flags.sh \ + /contrib/ci/scripts/set_generator_args.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/build_z3_cmake.sh + +# Test building docs +ADD \ + /contrib/ci/scripts/test_z3_docs.sh \ + /contrib/ci/scripts/run_quiet.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_docs.sh + +# Test examples +ADD \ + /contrib/ci/scripts/test_z3_examples_cmake.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_examples_cmake.sh + +# Run unit tests +ADD \ + /contrib/ci/scripts/test_z3_unit_tests_cmake.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_unit_tests_cmake.sh + +# Run system tests +ADD \ + /contrib/ci/scripts/test_z3_system_tests.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_system_tests.sh + +# Test install +ADD \ + /contrib/ci/scripts/test_z3_install_cmake.sh \ + ${Z3_SRC_DIR}/contrib/ci/scripts/ +RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_install_cmake.sh diff --git a/contrib/ci/README.md b/contrib/ci/README.md new file mode 100644 index 000000000..31bb504b6 --- /dev/null +++ b/contrib/ci/README.md @@ -0,0 +1,113 @@ +# Continous integration scripts + +## TravisCI + +For testing on Linux and macOS we use [TravisCI](https://travis-ci.org/) + +TravisCI consumes the `.travis.yml` file in the root of the repository +to tell it how to build and test Z3. + +However the logic for building and test Z3 is kept out of this file +and instead in a set of scripts in `scripts/`. This avoids +coupling the build to TravisCI tightly so we can migrate to another +service if required in the future. + +The scripts rely on a set of environment variables to control the configuration +of the build. The `.travis.yml` declares a list of configuration with each +configuration setting different environment variables. + +Note that the build scripts currently only support Z3 built with CMake. Support +for building Z3 using the older Python/Makefile build system might be added in +the future. + +### Configuration variables + +* `ASAN_BUILD` - Do [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) build (`0` or `1`) +* `BUILD_DOCS` - Build API documentation (`0` or `1`) +* `C_COMPILER` - Path to C Compiler +* `CXX_COMPILER` - Path to C++ Compiler +* `DOTNET_BINDINGS` - Build and test .NET API bindings (`0` or `1`) +* `JAVA_BINDINGS` - Build and test Java API bindings (`0` or `1`) +* `NO_SUPPRESS_OUTPUT` - Don't suppress output of some commands (`0` or `1`) +* `PYTHON_BINDINGS` - Build and test Python API bindings (`0` or `1`) +* `RUN_SYSTEM_TESTS` - Run system tests (`0` or `1`) +* `RUN_UNIT_TESTS` - Run unit tests (`0` or `1`) +* `TARGET_ARCH` - Target architecture (`x86_64` or `i686`) +* `TEST_INSTALL` - Test running `install` target (`0` or `1`) +* `UBSAN_BUILD` - Do [UndefinedBehaviourSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) build (`0` or `1`) +* `USE_LIBGMP` - Use [GNU multiple precision library](https://gmplib.org/) (`0` or `1`) +* `USE_LTO` - Link binaries using link time optimization (`0` or `1`) +* `USE_OPENMP` - Use OpenMP (`0` or `1`) +* `Z3_BUILD_TYPE` - CMake build type (`RelWithDebInfo`, `Release`, `Debug`, or `MinSizeRel`) +* `Z3_CMAKE_GENERATOR` - CMake generator (`Ninja` or `Unix Makefiles`) +* `Z3_VERBOSE_BUILD_OUTPUT` - Show compile commands in CMake builds (`0` or `1`) +* `Z3_STATIC_BUILD` - Build Z3 binaries and libraries statically (`0` or `1`) +* `Z3_SYSTEM_TEST_GIT_REVISION` - Git revision of [z3test](https://github.com/Z3Prover/z3test). If empty lastest revision will be used. + +### Linux + +For Linux we use Docker to perform the build so that it easily reproducible +on a local machine and so that we can avoid depending on TravisCI's environment +and instead use a Linux distribution of our choice. + +The `scripts/travis_ci_linux_entry_point.sh` script + +1. Creates a base image containing all the dependencies needed to build and test Z3 +2. Builds and tests Z3 using the base image propagating configuration environment + variables (if set) into the build using the `--build-arg` argument of the `docker run` + command. + +If an environemnt variable is not set a defaults value is used which can be +found in `Dockerfiles/z3_build.Dockerfile`. + +#### Linux specific configuration variables + +* `LINUX_BASE` - The base docker image identifier to use (`ubuntu_16.04`, `ubuntu32_16.04`, or `ubuntu_14.04`). + +#### Reproducing a build locally + +A build can be reproduced locally by using the `scripts/travis_ci_linux_entry_point.sh` +script and setting the appropriate environment variable. + +For example lets say we wanted to reproduce the build below. + +```yaml + + - LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo +``` + +This can be done by running the command + +```bash +LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo scripts/travis_ci_linux_entry_point.sh +``` + +The `docker build` command which we use internally supports caching. What this +means in practice is that re-running the above command will re-use successfully +completed stages of the build provided they haven't changed. This requires that +the `Dockerfiles/z3_build.Dockerfile` is carefully crafted to avoid invalidating +the cache when unrelated files sent to the build context change. + +#### TravisCI docker image cache + +To improve build times the Z3 base docker images are cached using +[TravisCI's cache directory feature](https://docs.travis-ci.com/user/caching). +If the `DOCKER_TRAVIS_CI_CACHE_DIR` environment variable is set (see `.travis.yml`) +then the directory pointed to by the environment variable is used as a cache +for Docker images. + +The logic for this can be found in `scripts/travis_ci_linux_entry_point.sh`. +The build time improvements are rather modest (~ 2 minutes) and the cache is +rather large due to TravisCI giving each configuration its own cache. So this +feature might be removed in the future. + +It may be better to just build the base image once (outside of TravisCI), upload +it to [DockerHub](https://hub.docker.com/) and have the build pull down the pre-built +image everytime. + +An [organization](https://hub.docker.com/u/z3prover/) has been created on +DockerHub for this. + +### macOS + +Not yet implemented. diff --git a/contrib/ci/maintainers.txt b/contrib/ci/maintainers.txt new file mode 100644 index 000000000..caa6798c6 --- /dev/null +++ b/contrib/ci/maintainers.txt @@ -0,0 +1,3 @@ +# Maintainers + +- Dan Liew (@delcypher) diff --git a/contrib/ci/scripts/build_z3_cmake.sh b/contrib/ci/scripts/build_z3_cmake.sh new file mode 100755 index 000000000..98a9724c7 --- /dev/null +++ b/contrib/ci/scripts/build_z3_cmake.sh @@ -0,0 +1,128 @@ +#!/bin/bash +# This script builds Z3 + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +set -x +set -e +set -o pipefail + +: ${Z3_SRC_DIR?"Z3_SRC_DIR must be specified"} +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} +: ${Z3_BUILD_TYPE?"Z3_BUILD_TYPE must be specified"} +: ${Z3_CMAKE_GENERATOR?"Z3_CMAKE_GENERATOR must be specified"} +: ${Z3_STATIC_BUILD?"Z3_STATIC_BUILD must be specified"} +: ${USE_OPENMP?"USE_OPENMP must be specified"} +: ${USE_LIBGMP?"USE_LIBGMP must be specified"} +: ${BUILD_DOCS?"BUILD_DOCS must be specified"} +: ${PYTHON_EXECUTABLE?"PYTHON_EXECUTABLE must be specified"} +: ${PYTHON_BINDINGS?"PYTHON_BINDINGS must be specified"} +: ${DOTNET_BINDINGS?"DOTNET_BINDINGS must be specified"} +: ${JAVA_BINDINGS?"JAVA_BINDINGS must be specified"} +: ${USE_LTO?"USE_LTO must be specified"} +: ${Z3_INSTALL_PREFIX?"Z3_INSTALL_PREFIX"} + +ADDITIONAL_Z3_OPTS=() + +# Static or dynamic libz3 +if [ "X${Z3_STATIC_BUILD}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=('-DBUILD_LIBZ3_SHARED=OFF') +else + ADDITIONAL_Z3_OPTS+=('-DBUILD_LIBZ3_SHARED=ON') +fi + +# Use OpenMP? +if [ "X${USE_OPENMP}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=('-DUSE_OPENMP=ON') +else + ADDITIONAL_Z3_OPTS+=('-DUSE_OPENMP=OFF') +fi + +# Use LibGMP? +if [ "X${USE_LIBGMP}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=('-DUSE_LIB_GMP=ON') +else + ADDITIONAL_Z3_OPTS+=('-DUSE_LIB_GMP=OFF') +fi + +# Use link time optimziation? +if [ "X${USE_LTO}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=('-DLINK_TIME_OPTIMIZATION=ON') +else + ADDITIONAL_Z3_OPTS+=('-DLINK_TIME_OPTIMIZATION=OFF') +fi + +# Build API docs? +if [ "X${BUILD_DOCS}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_DOCUMENTATION=ON' \ + '-DALWAYS_BUILD_DOCS=OFF' \ + ) +else + ADDITIONAL_Z3_OPTS+=('-DBUILD_DOCUMENTATION=OFF') +fi + +# Python bindings? +if [ "X${PYTHON_BINDINGS}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_PYTHON_BINDINGS=ON' \ + '-DINSTALL_PYTHON_BINDINGS=ON' \ + ) +else + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_PYTHON_BINDINGS=OFF' \ + '-DINSTALL_PYTHON_BINDINGS=OFF' \ + ) +fi + +# .NET bindings? +if [ "X${DOTNET_BINDINGS}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_DOTNET_BINDINGS=ON' \ + '-DINSTALL_DOTNET_BINDINGS=ON' \ + ) +else + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_DOTNET_BINDINGS=OFF' \ + '-DINSTALL_DOTNET_BINDINGS=OFF' \ + ) +fi + +# Java bindings? +if [ "X${JAVA_BINDINGS}" = "X1" ]; then + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_JAVA_BINDINGS=ON' \ + '-DINSTALL_JAVA_BINDINGS=ON' \ + ) +else + ADDITIONAL_Z3_OPTS+=( \ + '-DBUILD_JAVA_BINDINGS=OFF' \ + '-DINSTALL_JAVA_BINDINGS=OFF' \ + ) +fi + +# Set compiler flags +source ${SCRIPT_DIR}/set_compiler_flags.sh + +# Sanity check +if [ ! -e "${Z3_SRC_DIR}/CMakeLists.txt" ]; then + echo "Z3_SRC_DIR is invalid" + exit 1 +fi + +# Make build tree +mkdir -p "${Z3_BUILD_DIR}" +cd "${Z3_BUILD_DIR}" + +# Configure +cmake \ + -G "${Z3_CMAKE_GENERATOR}" \ + -DCMAKE_BUILD_TYPE=${Z3_BUILD_TYPE} \ + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} \ + -DCMAKE_INSTALL_PREFIX=${Z3_INSTALL_PREFIX} \ + "${ADDITIONAL_Z3_OPTS[@]}" \ + "${Z3_SRC_DIR}" + +# Build +source ${SCRIPT_DIR}/set_generator_args.sh +cmake --build $(pwd) "${GENERATOR_ARGS[@]}" diff --git a/contrib/ci/scripts/run_quiet.sh b/contrib/ci/scripts/run_quiet.sh new file mode 100644 index 000000000..5abc910e8 --- /dev/null +++ b/contrib/ci/scripts/run_quiet.sh @@ -0,0 +1,41 @@ +# Simple wrapper function that runs a command suppressing +# it's output. However it's output will be shown in the +# case that `NO_SUPPRESS_OUTPUT` is set to `1` or the command +# fails. +# +# The use case for this trying to avoid large logs on TravisCI +function run_quiet() { + if [ "X${NO_SUPPRESS_OUTPUT}" = "X1" ]; then + "${@}" + else + OLD_SETTINGS="$-" + set +x + set +e + TMP_DIR="${TMP_DIR:-/tmp/}" + STDOUT="${TMP_DIR}/$$.stdout" + STDERR="${TMP_DIR}/$$.stderr" + "${@}" > "${STDOUT}" 2> "${STDERR}" + EXIT_STATUS="$?" + if [ "${EXIT_STATUS}" -ne 0 ]; then + echo "Command \"$@\" failed" + echo "EXIT CODE: ${EXIT_STATUS}" + echo "STDOUT" + echo "" + echo "\`\`\`" + cat ${STDOUT} + echo "\`\`\`" + echo "" + echo "STDERR" + echo "" + echo "\`\`\`" + cat ${STDERR} + echo "\`\`\`" + echo "" + fi + # Clean up + rm "${STDOUT}" "${STDERR}" + [ $( echo "${OLD_SETTINGS}" | grep -c 'e') -ne 0 ] && set -e + [ $( echo "${OLD_SETTINGS}" | grep -c 'x') -ne 0 ] && set -x + return ${EXIT_STATUS} + fi +} diff --git a/contrib/ci/scripts/set_compiler_flags.sh b/contrib/ci/scripts/set_compiler_flags.sh new file mode 100644 index 000000000..7efdecdac --- /dev/null +++ b/contrib/ci/scripts/set_compiler_flags.sh @@ -0,0 +1,46 @@ +# This script should is intended to be included by other +# scripts and should not be executed directly + +: ${TARGET_ARCH?"TARGET_ARCH must be specified"} +: ${ASAN_BUILD?"ASAN_BUILD must be specified"} +: ${UBSAN_BUILD?"UBSAN_BUILD must be specified"} +: ${CC?"CC must be specified"} +: ${CXX?"CXX must be specified"} + +case ${TARGET_ARCH} in + x86_64) + CXXFLAGS="${CXXFLAGS} -m64" + CFLAGS="${CFLAGS} -m64" + ;; + i686) + CXXFLAGS="${CXXFLAGS} -m32" + CFLAGS="${CFLAGS} -m32" + ;; + *) + echo "Unknown arch \"${TARGET_ARCH}\"" + exit 1 +esac + +if [ "X${ASAN_BUILD}" = "X1" ]; then + CXXFLAGS="${CXXFLAGS} -fsanitize=address -fno-omit-frame-pointer" + CFLAGS="${CFLAGS} -fsanitize=address -fno-omit-frame-pointer" +fi + +if [ "X${UBSAN_BUILD}" = "X1" ]; then + CXXFLAGS="${CXXFLAGS} -fsanitize=undefined" + CFLAGS="${CFLAGS} -fsanitize=undefined" +fi + +# Report flags +echo "CXXFLAGS: ${CXXFLAGS}" +echo "CFLAGS: ${CFLAGS}" + +# Report compiler +echo "CC: ${CC}" +${CC} --version +echo "CXX: ${CXX}" +${CXX} --version + +# Export the values +export CFLAGS +export CXXFLAGS diff --git a/contrib/ci/scripts/set_generator_args.sh b/contrib/ci/scripts/set_generator_args.sh new file mode 100644 index 000000000..0ef7b76aa --- /dev/null +++ b/contrib/ci/scripts/set_generator_args.sh @@ -0,0 +1,20 @@ +# This script should is intended to be included by other +# scripts and should not be executed directly + +: ${Z3_CMAKE_GENERATOR?"Z3_CMAKE_GENERATOR must be specified"} +: ${Z3_VERBOSE_BUILD_OUTPUT?"Z3_VERBOSE_BUILD_OUTPUT must be specified"} + +GENERATOR_ARGS=('--') +if [ "${Z3_CMAKE_GENERATOR}" = "Unix Makefiles" ]; then + GENERATOR_ARGS+=("-j$(nproc)") + if [ "X${Z3_VERBOSE_BUILD_OUTPUT}" = "X1" ]; then + GENERATOR_ARGS+=("VERBOSE=1") + fi +elif [ "${Z3_CMAKE_GENERATOR}" = "Ninja" ]; then + if [ "X${Z3_VERBOSE_BUILD_OUTPUT}" = "X1" ]; then + GENERATOR_ARGS+=("-v") + fi +else + echo "Unknown CMake generator \"${Z3_CMAKE_GENERATOR}\"" + exit 1 +fi diff --git a/contrib/ci/scripts/test_z3_docs.sh b/contrib/ci/scripts/test_z3_docs.sh new file mode 100755 index 000000000..6a65ffedd --- /dev/null +++ b/contrib/ci/scripts/test_z3_docs.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" +. ${SCRIPT_DIR}/run_quiet.sh + +set -x +set -e +set -o pipefail + +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} +: ${BUILD_DOCS?"BUILD_DOCS must be specified"} + +# Set CMake generator args +source ${SCRIPT_DIR}/set_generator_args.sh + +cd "${Z3_BUILD_DIR}" + +# Generate documentation +if [ "X${BUILD_DOCS}" = "X1" ]; then + # TODO: Make quiet once we've fixed the build + run_quiet cmake --build $(pwd) --target api_docs "${GENERATOR_ARGS[@]}" +fi + +# TODO: Test or perhaps deploy the built docs? diff --git a/contrib/ci/scripts/test_z3_examples_cmake.sh b/contrib/ci/scripts/test_z3_examples_cmake.sh new file mode 100755 index 000000000..2eda3de7b --- /dev/null +++ b/contrib/ci/scripts/test_z3_examples_cmake.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# This script tests Z3 + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" +. ${SCRIPT_DIR}/run_quiet.sh + +set -x +set -e +set -o pipefail +: ${Z3_SRC_DIR?"Z3_SRC_DIR must be specified"} +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} +: ${PYTHON_BINDINGS?"PYTHON_BINDINGS must be specified"} +: ${PYTHON_EXECUTABLE?"PYTHON_EXECUTABLE must be specified"} +: ${DOTNET_BINDINGS?"DOTNET_BINDINGS must be specified"} +: ${JAVA_BINDINGS?"JAVA_BINDINGS must be specified"} + +# Set compiler flags +source ${SCRIPT_DIR}/set_compiler_flags.sh + +# Set CMake generator args +source ${SCRIPT_DIR}/set_generator_args.sh + +cd "${Z3_BUILD_DIR}" + +# Build and run C example +cmake --build $(pwd) --target c_example "${GENERATOR_ARGS[@]}" +run_quiet examples/c_example_build_dir/c_example + +# Build and run C++ example +cmake --build $(pwd) --target cpp_example "${GENERATOR_ARGS[@]}" +run_quiet examples/cpp_example_build_dir/cpp_example + +# Build and run tptp5 example +cmake --build $(pwd) --target z3_tptp5 "${GENERATOR_ARGS[@]}" +# FIXME: Do something more useful with example +run_quiet examples/tptp_build_dir/z3_tptp5 -help + +# Build an run c_maxsat_example +cmake --build $(pwd) --target c_maxsat_example "${GENERATOR_ARGS[@]}" +run_quiet \ + examples/c_maxsat_example_build_dir/c_maxsat_example \ + ${Z3_SRC_DIR}/examples/maxsat/ex.smt + + +if [ "X${PYTHON_BINDINGS}" = "X1" ]; then + # Run python examples + # `all_interval_series.py` produces a lot of output so just throw + # away output. + # TODO: This example is slow should we remove it from testing? + run_quiet ${PYTHON_EXECUTABLE} python/all_interval_series.py + run_quiet ${PYTHON_EXECUTABLE} python/complex.py + run_quiet ${PYTHON_EXECUTABLE} python/example.py + # FIXME: `hamiltonian.py` example is disabled because its too slow. + #${PYTHON_EXECUTABLE} python/hamiltonian.py + run_quiet ${PYTHON_EXECUTABLE} python/marco.py + run_quiet ${PYTHON_EXECUTABLE} python/mss.py + run_quiet ${PYTHON_EXECUTABLE} python/socrates.py + run_quiet ${PYTHON_EXECUTABLE} python/visitor.py + run_quiet ${PYTHON_EXECUTABLE} python/z3test.py +fi + +if [ "X${DOTNET_BINDINGS}" = "X1" ]; then + # Build .NET example + # FIXME: Move compliation step into CMake target + mcs ${Z3_SRC_DIR}/examples/dotnet/Program.cs /target:exe /out:dotnet_test.exe /reference:Microsoft.Z3.dll /r:System.Numerics.dll + # Run .NET example + run_quiet mono ./dotnet_test.exe +fi + +if [ "X${JAVA_BINDINGS}" = "X1" ]; then + # Build Java example + # FIXME: Move compilation step into CMake target + mkdir -p examples/java + cp ${Z3_SRC_DIR}/examples/java/JavaExample.java examples/java/ + javac examples/java/JavaExample.java -classpath com.microsoft.z3.jar + # Run Java example + if [ "$(uname)" = "Darwin" ]; then + # macOS + export DYLD_LIBRARY_PATH=$(pwd):${DYLD_LIBRARY_PATH} + else + # Assume Linux for now + export LD_LIBRARY_PATH=$(pwd):${LD_LIBRARY_PATH} + fi + run_quiet java -cp .:examples/java:com.microsoft.z3.jar JavaExample +fi + diff --git a/contrib/ci/scripts/test_z3_install_cmake.sh b/contrib/ci/scripts/test_z3_install_cmake.sh new file mode 100755 index 000000000..804158f6f --- /dev/null +++ b/contrib/ci/scripts/test_z3_install_cmake.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +set -x +set -e +set -o pipefail + +: ${TEST_INSTALL?"TEST_INSTALL must be specified"} +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} + +if [ "X${TEST_INSTALL}" != "X1" ]; then + echo "Skipping install" + exit 0 +fi + +# Set CMake generator args +source ${SCRIPT_DIR}/set_generator_args.sh + +cd "${Z3_BUILD_DIR}" + +sudo cmake --build $(pwd) --target install "${GENERATOR_ARGS[@]}" + +# TODO: Test the installed version in some way diff --git a/contrib/ci/scripts/test_z3_system_tests.sh b/contrib/ci/scripts/test_z3_system_tests.sh new file mode 100755 index 000000000..dfb1084a4 --- /dev/null +++ b/contrib/ci/scripts/test_z3_system_tests.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +set -x +set -e +set -o pipefail + +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} +: ${Z3_BUILD_TYPE?"Z3_BUILD_TYPE must be specified"} +: ${RUN_SYSTEM_TESTS?"RUN_SYSTEM_TESTS must be speicifed"} +: ${PYTHON_BINDINGS?"PYTHON_BINDINGS must be specified"} +: ${PYTHON_EXECUTABLE?"PYTHON_EXECUTABLE must be specified"} +: ${Z3_SYSTEM_TEST_DIR?"Z3_SYSTEM_TEST_DIR must be specified"} + +if [ "X${RUN_SYSTEM_TESTS}" != "X1" ]; then + echo "Skipping system tests" + exit 0 +fi + +Z3_EXE="${Z3_BUILD_DIR}/z3" +Z3_LIB_DIR="${Z3_BUILD_DIR}" + +# Set value if not already defined externally +Z3_SYSTEM_TEST_GIT_URL="${Z3_GIT_URL:-https://github.com/Z3Prover/z3test.git}" + +# Clone repo to destination +mkdir -p "${Z3_SYSTEM_TEST_GIT_URL}" +git clone "${Z3_SYSTEM_TEST_GIT_URL}" "${Z3_SYSTEM_TEST_DIR}" +cd "${Z3_SYSTEM_TEST_DIR}" + +if [ -n "${Z3_SYSTEM_TEST_GIT_REVISION}" ]; then + # If a particular revision is requested then check it out. + # This is useful for reproducible builds + git checkout "${Z3_SYSTEM_TEST_GIT_REVISION}" +fi + +############################################################################### +# Run system tests +############################################################################### + +# SMTLIBv2 tests +${PYTHON_EXECUTABLE} scripts/test_benchmarks.py "${Z3_EXE}" regressions/smt2 + +${PYTHON_EXECUTABLE} scripts/test_benchmarks.py "${Z3_EXE}" regressions/smt2-extra + +if [ "X${Z3_BUILD_TYPE}" = "XDebug" ]; then + ${PYTHON_EXECUTABLE} scripts/test_benchmarks.py "${Z3_EXE}" regressions/smt2-debug +fi + +if [ "X${PYTHON_BINDINGS}" = "X1" ]; then + # Run python binding tests + ${PYTHON_EXECUTABLE} scripts/test_pyscripts.py "${Z3_LIB_DIR}" regressions/python/ +fi + +# FIXME: Run `scripts/test_cs.py` once it has been modified to support mono diff --git a/contrib/ci/scripts/test_z3_unit_tests_cmake.sh b/contrib/ci/scripts/test_z3_unit_tests_cmake.sh new file mode 100755 index 000000000..0d8e59b0f --- /dev/null +++ b/contrib/ci/scripts/test_z3_unit_tests_cmake.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +set -x +set -e +set -o pipefail + +: ${Z3_BUILD_DIR?"Z3_BUILD_DIR must be specified"} +: ${RUN_UNIT_TESTS?"RUN_UNIT_TESTS must be specified"} + +if [ "X${RUN_UNIT_TESTS}" != "X1" ]; then + echo "Skipping unit tests" + exit 0 +fi + +# Set CMake generator args +source ${SCRIPT_DIR}/set_generator_args.sh + +cd "${Z3_BUILD_DIR}" + +# Build and run internal tests +cmake --build $(pwd) --target test-z3 "${GENERATOR_ARGS[@]}" +./test-z3 diff --git a/contrib/ci/scripts/travis_ci_entry_point.sh b/contrib/ci/scripts/travis_ci_entry_point.sh new file mode 100755 index 000000000..41bde7230 --- /dev/null +++ b/contrib/ci/scripts/travis_ci_entry_point.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +set -x +set -e +set -o pipefail + +: ${TRAVIS_OS_NAME?"TRAVIS_OS_NAME should be set"} + +if [ "${TRAVIS_OS_NAME}" = "osx" ]; then + ${SCRIPT_DIR}/travis_ci_osx_entry_point.sh +elif [ "${TRAVIS_OS_NAME}" = "linux" ]; then + ${SCRIPT_DIR}/travis_ci_linux_entry_point.sh +else + echo "Unsupported OS \"${TRAVIS_OS_NAME}\"" + exit 1 +fi diff --git a/contrib/ci/scripts/travis_ci_linux_entry_point.sh b/contrib/ci/scripts/travis_ci_linux_entry_point.sh new file mode 100755 index 000000000..21b97788f --- /dev/null +++ b/contrib/ci/scripts/travis_ci_linux_entry_point.sh @@ -0,0 +1,208 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +set -x +set -e +set -o pipefail + +DOCKER_FILE_DIR="$(cd ${SCRIPT_DIR}/../Dockerfiles; echo $PWD)" + +: ${LINUX_BASE?"LINUX_BASE must be specified"} + + + +# Sanity check. Current working directory should be repo root +if [ ! -f "./README.md" ]; then + echo "Current working directory should be repo root" + exit 1 +fi + +BUILD_OPTS=() +# Override options if they have been provided. +# Otherwise the defaults in the Docker file will be used +if [ -n "${Z3_CMAKE_GENERATOR}" ]; then + BUILD_OPTS+=("--build-arg" "Z3_CMAKE_GENERATOR=${Z3_CMAKE_GENERATOR}") +fi + +if [ -n "${USE_OPENMP}" ]; then + BUILD_OPTS+=("--build-arg" "USE_OPENMP=${USE_OPENMP}") +fi + +if [ -n "${USE_LIBGMP}" ]; then + BUILD_OPTS+=("--build-arg" "USE_LIBGMP=${USE_LIBGMP}") +fi + +if [ -n "${BUILD_DOCS}" ]; then + BUILD_OPTS+=("--build-arg" "BUILD_DOCS=${BUILD_DOCS}") +fi + +if [ -n "${PYTHON_EXECUTABLE}" ]; then + BUILD_OPTS+=("--build-arg" "PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}") +fi + +if [ -n "${PYTHON_BINDINGS}" ]; then + BUILD_OPTS+=("--build-arg" "PYTHON_BINDINGS=${PYTHON_BINDINGS}") +fi + +if [ -n "${DOTNET_BINDINGS}" ]; then + BUILD_OPTS+=("--build-arg" "DOTNET_BINDINGS=${DOTNET_BINDINGS}") +fi + +if [ -n "${JAVA_BINDINGS}" ]; then + BUILD_OPTS+=("--build-arg" "JAVA_BINDINGS=${JAVA_BINDINGS}") +fi + +if [ -n "${USE_LTO}" ]; then + BUILD_OPTS+=("--build-arg" "USE_LTO=${USE_LTO}") +fi + +if [ -n "${Z3_INSTALL_PREFIX}" ]; then + BUILD_OPTS+=("--build-arg" "Z3_INSTALL_PREFIX=${Z3_INSTALL_PREFIX}") +fi + +# TravisCI reserves CC for itself so use a different name +if [ -n "${C_COMPILER}" ]; then + BUILD_OPTS+=("--build-arg" "CC=${C_COMPILER}") +fi + +# TravisCI reserves CXX for itself so use a different name +if [ -n "${CXX_COMPILER}" ]; then + BUILD_OPTS+=("--build-arg" "CXX=${CXX_COMPILER}") +fi + +if [ -n "${TARGET_ARCH}" ]; then + BUILD_OPTS+=("--build-arg" "TARGET_ARCH=${TARGET_ARCH}") +fi + +if [ -n "${ASAN_BUILD}" ]; then + BUILD_OPTS+=("--build-arg" "ASAN_BUILD=${ASAN_BUILD}") +fi + +if [ -n "${UBSAN_BUILD}" ]; then + BUILD_OPTS+=("--build-arg" "UBSAN_BUILD=${UBSAN_BUILD}") +fi + +if [ -n "${TEST_INSTALL}" ]; then + BUILD_OPTS+=("--build-arg" "TEST_INSTALL=${TEST_INSTALL}") +fi + +if [ -n "${RUN_SYSTEM_TESTS}" ]; then + BUILD_OPTS+=("--build-arg" "RUN_SYSTEM_TESTS=${RUN_SYSTEM_TESTS}") +fi + +if [ -n "${Z3_SYSTEM_TEST_GIT_REVISION}" ]; then + BUILD_OPTS+=( \ + "--build-arg" \ + "Z3_SYSTEM_TEST_GIT_REVISION=${Z3_SYSTEM_TEST_GIT_REVISION}" \ + ) +fi + +if [ -n "${RUN_UNIT_TESTS}" ]; then + BUILD_OPTS+=("--build-arg" "RUN_UNIT_TESTS=${RUN_UNIT_TESTS}") +fi + +if [ -n "${Z3_VERBOSE_BUILD_OUTPUT}" ]; then + BUILD_OPTS+=( \ + "--build-arg" \ + "Z3_VERBOSE_BUILD_OUTPUT=${Z3_VERBOSE_BUILD_OUTPUT}" \ + ) +fi + +if [ -n "${Z3_STATIC_BUILD}" ]; then + BUILD_OPTS+=("--build-arg" "Z3_STATIC_BUILD=${Z3_STATIC_BUILD}") +fi + +if [ -n "${NO_SUPPRESS_OUTPUT}" ]; then + BUILD_OPTS+=( \ + "--build-arg" \ + "NO_SUPPRESS_OUTPUT=${NO_SUPPRESS_OUTPUT}" \ + ) +fi + +case ${LINUX_BASE} in + ubuntu_14.04) + BASE_DOCKER_FILE="${DOCKER_FILE_DIR}/z3_base_ubuntu_14.04.Dockerfile" + BASE_DOCKER_IMAGE_NAME="z3_base_ubuntu:14.04" + ;; + ubuntu_16.04) + BASE_DOCKER_FILE="${DOCKER_FILE_DIR}/z3_base_ubuntu_16.04.Dockerfile" + BASE_DOCKER_IMAGE_NAME="z3_base_ubuntu:16.04" + ;; + ubuntu32_16.04) + BASE_DOCKER_FILE="${DOCKER_FILE_DIR}/z3_base_ubuntu32_16.04.Dockerfile" + BASE_DOCKER_IMAGE_NAME="z3_base_ubuntu32:16.04" + ;; + *) + echo "Unknown Linux base ${LINUX_BASE}" + exit 1 + ;; +esac + +# Initially assume that we need to build the base Docker image +MUST_BUILD=1 + +# Travis CI persistent cache. +# +# This inspired by http://rundef.com/fast-travis-ci-docker-build . +# The idea is to cache the built image for subsequent builds to +# reduce build time. +if [ -n "${DOCKER_TRAVIS_CI_CACHE_DIR}" ]; then + CHECKSUM_FILE="${DOCKER_TRAVIS_CI_CACHE_DIR}/${BASE_DOCKER_IMAGE_NAME}.chksum" + CACHED_DOCKER_IMAGE="${DOCKER_TRAVIS_CI_CACHE_DIR}/${BASE_DOCKER_IMAGE_NAME}.gz" + if [ -f "${CACHED_DOCKER_IMAGE}" ]; then + # There's a cached image to use. Check the checksums of the Dockerfile + # match. If they don't that implies we need to build a fresh image. + if [ -f "${CHECKSUM_FILE}" ]; then + CURRENT_DOCKERFILE_CHECKSUM=$(sha256sum "${BASE_DOCKER_FILE}" | awk '{ print $1 }') + CACHED_DOCKERFILE_CHECKSUM=$(cat "${CHECKSUM_FILE}") + if [ "X${CURRENT_DOCKERFILE_CHECKSUM}" = "X${CACHED_DOCKERFILE_CHECKSUM}" ]; then + # Load the cached image + MUST_BUILD=0 + gunzip --stdout "${CACHED_DOCKER_IMAGE}" | docker load + fi + fi + fi +fi + +if [ "${MUST_BUILD}" -eq 1 ]; then + # The base image contains all the dependencies we want to build + # Z3. + docker build -t "${BASE_DOCKER_IMAGE_NAME}" - < "${BASE_DOCKER_FILE}" + + if [ -n "${DOCKER_TRAVIS_CI_CACHE_DIR}" ]; then + # Write image and checksum to cache + docker save "${BASE_DOCKER_IMAGE_NAME}" | \ + gzip > "${CACHED_DOCKER_IMAGE}" + sha256sum "${BASE_DOCKER_FILE}" | awk '{ print $1 }' > \ + "${CHECKSUM_FILE}" + fi +fi + + +DOCKER_MAJOR_VERSION=$(docker info --format '{{.ServerVersion}}' | sed 's/^\([0-9]\+\)\.\([0-9]\+\).*$/\1/') +DOCKER_MINOR_VERSION=$(docker info --format '{{.ServerVersion}}' | sed 's/^\([0-9]\+\)\.\([0-9]\+\).*$/\2/') +DOCKER_BUILD_FILE="${DOCKER_FILE_DIR}/z3_build.Dockerfile" + +if [ "${DOCKER_MAJOR_VERSION}${DOCKER_MINOR_VERSION}" -lt 1705 ]; then + # Workaround limitation in older Docker versions where the FROM + # command cannot be parameterized with an ARG. + sed \ + -e '/^ARG DOCKER_IMAGE_BASE/d' \ + -e 's/${DOCKER_IMAGE_BASE}/'"${BASE_DOCKER_IMAGE_NAME}/" \ + "${DOCKER_BUILD_FILE}" > "${DOCKER_BUILD_FILE}.patched" + DOCKER_BUILD_FILE="${DOCKER_BUILD_FILE}.patched" +else + # This feature landed in Docker 17.05 + # See https://github.com/moby/moby/pull/31352 + BUILD_OPTS+=( \ + "--build-arg" \ + "DOCKER_IMAGE_BASE=${BASE_DOCKER_IMAGE_NAME}" \ + ) +fi + +# Now build Z3 and test it using the created base image +docker build \ + -f "${DOCKER_BUILD_FILE}" \ + "${BUILD_OPTS[@]}" \ + . diff --git a/contrib/ci/scripts/travis_ci_osx_entry_point.sh b/contrib/ci/scripts/travis_ci_osx_entry_point.sh new file mode 100755 index 000000000..03be81647 --- /dev/null +++ b/contrib/ci/scripts/travis_ci_osx_entry_point.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )" + +set -x +set -e +set -o pipefail + +echo "Not implemented" +exit 1 From 08524a2d90e4402e72a7735dfa022b909cbe629e Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 1 Jul 2017 11:47:17 -0700 Subject: [PATCH 100/159] cleanup for warning message Signed-off-by: Nikolaj Bjorner --- src/ast/rewriter/arith_rewriter.cpp | 2 +- src/muz/base/dl_rule_set.cpp | 2 +- src/muz/rel/dl_relation_manager.cpp | 2 +- src/opt/wmax.cpp | 2 +- src/qe/qe_arith_plugin.cpp | 2 +- src/smt/smt_consequences.cpp | 1 + src/smt/theory_lra.cpp | 8 +++-- src/smt/theory_seq.cpp | 34 +++++++++---------- .../portfolio/bounded_int2bv_solver.cpp | 4 +-- src/tactic/portfolio/enum2bv_solver.cpp | 4 +-- 10 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/ast/rewriter/arith_rewriter.cpp b/src/ast/rewriter/arith_rewriter.cpp index 2b2087e3b..258c28369 100644 --- a/src/ast/rewriter/arith_rewriter.cpp +++ b/src/ast/rewriter/arith_rewriter.cpp @@ -985,7 +985,7 @@ br_status arith_rewriter::mk_power_core(expr * arg1, expr * arg2, expr_ref & res br_status arith_rewriter::mk_to_int_core(expr * arg, expr_ref & result) { numeral a; - expr* x; + expr* x = 0; if (m_util.is_numeral(arg, a)) { result = m_util.mk_numeral(floor(a), true); return BR_DONE; diff --git a/src/muz/base/dl_rule_set.cpp b/src/muz/base/dl_rule_set.cpp index e9b383b56..229db4d27 100644 --- a/src/muz/base/dl_rule_set.cpp +++ b/src/muz/base/dl_rule_set.cpp @@ -668,7 +668,7 @@ namespace datalog { T * el = it->m_key; item_set * out_edges = it->m_value; - unsigned el_comp; + unsigned el_comp = 0; VERIFY( m_component_nums.find(el, el_comp) ); item_set::iterator eit = out_edges->begin(); diff --git a/src/muz/rel/dl_relation_manager.cpp b/src/muz/rel/dl_relation_manager.cpp index 74206a1f6..9e02a764f 100644 --- a/src/muz/rel/dl_relation_manager.cpp +++ b/src/muz/rel/dl_relation_manager.cpp @@ -294,7 +294,7 @@ namespace datalog { } table_relation_plugin & relation_manager::get_table_relation_plugin(table_plugin & tp) { - table_relation_plugin * res; + table_relation_plugin * res = 0; VERIFY( m_table_relation_plugins.find(&tp, res) ); return *res; } diff --git a/src/opt/wmax.cpp b/src/opt/wmax.cpp index 58d319a63..15b723c8c 100644 --- a/src/opt/wmax.cpp +++ b/src/opt/wmax.cpp @@ -216,7 +216,7 @@ namespace opt { rational remove_negations(smt::theory_wmaxsat& th, expr_ref_vector const& core, ptr_vector& keys, vector& weights) { rational min_weight(-1); for (unsigned i = 0; i < core.size(); ++i) { - expr* e; + expr* e = 0; VERIFY(m.is_not(core[i], e)); keys.push_back(m_keys[e]); rational weight = m_weights[e]; diff --git a/src/qe/qe_arith_plugin.cpp b/src/qe/qe_arith_plugin.cpp index 4281ec909..d8ae75256 100644 --- a/src/qe/qe_arith_plugin.cpp +++ b/src/qe/qe_arith_plugin.cpp @@ -2503,7 +2503,7 @@ public: } virtual void subst(contains_app& x, rational const& vl, expr_ref& fml, expr_ref* def) { - nlarith::branch_conditions *brs; + nlarith::branch_conditions *brs = 0; VERIFY (m_cache.find(x.x(), fml, brs)); SASSERT(vl.is_unsigned()); SASSERT(vl.get_unsigned() < brs->size()); diff --git a/src/smt/smt_consequences.cpp b/src/smt/smt_consequences.cpp index 65272207e..20813602e 100644 --- a/src/smt/smt_consequences.cpp +++ b/src/smt/smt_consequences.cpp @@ -103,6 +103,7 @@ namespace smt { void context::justify(literal lit, index_set& s) { ast_manager& m = m_manager; + (void)m; b_justification js = get_justification(lit.var()); switch (js.get_kind()) { case b_justification::CLAUSE: { diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 76e721faa..2bd4844e8 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -765,7 +765,7 @@ namespace smt { } void internalize_eq_eh(app * atom, bool_var) { - expr* lhs, *rhs; + expr* lhs = 0, *rhs = 0; VERIFY(m.is_eq(atom, lhs, rhs)); enode * n1 = get_enode(lhs); enode * n2 = get_enode(rhs); @@ -892,7 +892,7 @@ namespace smt { // to_int (to_real x) = x // to_real(to_int(x)) <= x < to_real(to_int(x)) + 1 void mk_to_int_axiom(app* n) { - expr* x, *y; + expr* x = 0, *y = 0; VERIFY (a.is_to_int(n, x)); if (a.is_to_real(x, y)) { mk_axiom(th.mk_eq(y, n, false)); @@ -908,7 +908,7 @@ namespace smt { // is_int(x) <=> to_real(to_int(x)) = x void mk_is_int_axiom(app* n) { - expr* x; + expr* x = 0; VERIFY(a.is_is_int(n, x)); literal eq = th.mk_eq(a.mk_to_real(a.mk_to_int(x)), x, false); literal is_int = ctx().get_literal(n); @@ -1299,12 +1299,14 @@ namespace smt { return; } int num_of_p = m_solver->settings().st().m_num_of_implied_bounds; + (void)num_of_p; local_bound_propagator bp(*this); m_solver->propagate_bounds_for_touched_rows(bp); if (m.canceled()) { return; } int new_num_of_p = m_solver->settings().st().m_num_of_implied_bounds; + (void)new_num_of_p; CTRACE("arith", new_num_of_p > num_of_p, tout << "found " << new_num_of_p << " implied bounds\n";); if (m_solver->get_status() == lean::lp_status::INFEASIBLE) { set_conflict(); diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index ea53f1342..dfb535f51 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -1074,7 +1074,7 @@ expr_ref theory_seq::mk_first(expr* s) { void theory_seq::mk_decompose(expr* e, expr_ref& head, expr_ref& tail) { - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; zstring s; if (m_util.str.is_empty(e)) { head = m_util.str.mk_unit(mk_nth(e, m_autil.mk_int(0))); @@ -1401,7 +1401,7 @@ bool theory_seq::occurs(expr* a, expr* b) { // true if a occurs under an interpreted function or under left/right selector. SASSERT(is_var(a)); SASSERT(m_todo.empty()); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; m_todo.push_back(b); while (!m_todo.empty()) { b = m_todo.back(); @@ -1990,7 +1990,7 @@ bool theory_seq::solve_nc(unsigned idx) { return true; } - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; if (m.is_eq(c, e1, e2)) { literal eq = mk_eq(e1, e2, false); propagate_lit(deps, 0, 0, ~eq); @@ -2316,7 +2316,7 @@ bool theory_seq::check_int_string() { bool theory_seq::add_stoi_axiom(expr* e) { context& ctx = get_context(); - expr* n; + expr* n = 0; rational val; TRACE("seq", tout << mk_pp(e, m) << "\n";); VERIFY(m_util.str.is_stoi(e, n)); @@ -2398,7 +2398,7 @@ expr_ref theory_seq::digit2int(expr* ch) { bool theory_seq::add_itos_axiom(expr* e) { context& ctx = get_context(); rational val; - expr* n; + expr* n = 0; TRACE("seq", tout << mk_pp(e, m) << "\n";); VERIFY(m_util.str.is_itos(e, n)); if (get_num_value(n, val)) { @@ -3197,7 +3197,7 @@ void theory_seq::add_indexof_axiom(expr* i) { */ void theory_seq::add_replace_axiom(expr* r) { - expr* a, *s, *t; + expr* a = 0, *s = 0, *t = 0; VERIFY(m_util.str.is_replace(r, a, s, t)); expr_ref x = mk_skolem(m_indexof_left, a, s); expr_ref y = mk_skolem(m_indexof_right, a, s); @@ -3330,7 +3330,7 @@ void theory_seq::add_itos_length_axiom(expr* len) { void theory_seq::propagate_in_re(expr* n, bool is_true) { TRACE("seq", tout << mk_pp(n, m) << " <- " << (is_true?"true":"false") << "\n";); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; VERIFY(m_util.str.is_in_re(n, e1, e2)); expr_ref tmp(n, m); @@ -3462,7 +3462,7 @@ bool theory_seq::get_length(expr* e, rational& val) const { if (!tha) return false; rational val1; expr_ref len(m), len_val(m); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; ptr_vector todo; todo.push_back(e); val.reset(); @@ -3522,7 +3522,7 @@ bool theory_seq::get_length(expr* e, rational& val) const { */ void theory_seq::add_extract_axiom(expr* e) { - expr* s, *i, *l; + expr* s = 0, *i = 0, *l = 0; VERIFY(m_util.str.is_extract(e, s, i, l)); if (is_tail(s, i, l)) { add_tail_axiom(e, s); @@ -3682,7 +3682,7 @@ void theory_seq::add_at_axiom(expr* e) { */ void theory_seq::propagate_step(literal lit, expr* step) { SASSERT(get_context().get_assignment(lit) == l_true); - expr* re, *acc, *s, *idx, *i, *j; + expr* re = 0, *acc = 0, *s = 0, *idx = 0, *i = 0, *j = 0; VERIFY(is_step(step, s, idx, re, i, j, acc)); TRACE("seq", tout << mk_pp(step, m) << " -> " << mk_pp(acc, m) << "\n";); propagate_lit(0, 1, &lit, mk_literal(acc)); @@ -3843,7 +3843,7 @@ void theory_seq::propagate_eq(dependency* deps, literal_vector const& _lits, exp void theory_seq::assign_eh(bool_var v, bool is_true) { context & ctx = get_context(); expr* e = ctx.bool_var2expr(v); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; expr_ref f(m); bool change = false; literal lit(v, !is_true); @@ -4191,7 +4191,7 @@ expr_ref theory_seq::mk_step(expr* s, expr* idx, expr* re, unsigned i, unsigned rej(s, idx, re, i) -> len(s) > idx if i is final */ void theory_seq::propagate_acc_rej_length(literal lit, expr* e) { - expr *s, * idx, *re; + expr *s = 0, *idx = 0, *re = 0; unsigned src; eautomaton* aut = 0; bool is_acc; @@ -4220,7 +4220,7 @@ bool theory_seq::add_accept2step(expr* acc, bool& change) { TRACE("seq", tout << mk_pp(acc, m) << "\n";); SASSERT(ctx.get_assignment(acc) == l_true); - expr *e, * idx, *re; + expr *e = 0, *idx = 0, *re = 0; expr_ref step(m); unsigned src; eautomaton* aut = 0; @@ -4299,7 +4299,7 @@ bool theory_seq::add_accept2step(expr* acc, bool& change) { bool theory_seq::add_step2accept(expr* step, bool& change) { context& ctx = get_context(); SASSERT(ctx.get_assignment(step) == l_true); - expr* re, *_acc, *s, *idx, *i, *j; + expr* re = 0, *_acc = 0, *s = 0, *idx = 0, *i = 0, *j = 0; VERIFY(is_step(step, s, idx, re, i, j, _acc)); literal acc1 = mk_accept(s, idx, re, i); switch (ctx.get_assignment(acc1)) { @@ -4348,7 +4348,7 @@ Recall we also have: bool theory_seq::add_reject2reject(expr* rej, bool& change) { context& ctx = get_context(); SASSERT(ctx.get_assignment(rej) == l_true); - expr* s, *idx, *re; + expr* s = 0, *idx = 0, *re = 0; unsigned src; rational r; eautomaton* aut = 0; @@ -4410,7 +4410,7 @@ bool theory_seq::add_reject2reject(expr* rej, bool& change) { void theory_seq::propagate_not_prefix(expr* e) { context& ctx = get_context(); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; VERIFY(m_util.str.is_prefix(e, e1, e2)); literal lit = ctx.get_literal(e); SASSERT(ctx.get_assignment(lit) == l_false); @@ -4439,7 +4439,7 @@ void theory_seq::propagate_not_prefix(expr* e) { void theory_seq::propagate_not_prefix2(expr* e) { context& ctx = get_context(); - expr* e1, *e2; + expr* e1 = 0, *e2 = 0; VERIFY(m_util.str.is_prefix(e, e1, e2)); literal lit = ctx.get_literal(e); SASSERT(ctx.get_assignment(lit) == l_false); diff --git a/src/tactic/portfolio/bounded_int2bv_solver.cpp b/src/tactic/portfolio/bounded_int2bv_solver.cpp index 83693abba..e293ade17 100644 --- a/src/tactic/portfolio/bounded_int2bv_solver.cpp +++ b/src/tactic/portfolio/bounded_int2bv_solver.cpp @@ -168,7 +168,7 @@ public: // translate bit-vector consequences back to integer values for (unsigned i = 0; i < consequences.size(); ++i) { - expr* a, *b, *u, *v; + expr* a = 0, *b = 0, *u = 0, *v = 0; func_decl* f; rational num; unsigned bvsize; @@ -228,7 +228,7 @@ private: for (; it != end; ++it) { expr* e = *it; rational lo, hi; - bool s1, s2; + bool s1 = false, s2 = false; SASSERT(is_uninterp_const(e)); func_decl* f = to_app(e)->get_decl(); diff --git a/src/tactic/portfolio/enum2bv_solver.cpp b/src/tactic/portfolio/enum2bv_solver.cpp index 35601f374..8c9ff122d 100644 --- a/src/tactic/portfolio/enum2bv_solver.cpp +++ b/src/tactic/portfolio/enum2bv_solver.cpp @@ -116,7 +116,7 @@ public: // translate enumeration constants to bit-vectors. for (unsigned i = 0; i < vars.size(); ++i) { - func_decl* f; + func_decl* f = 0; if (is_app(vars[i]) && is_uninterp_const(vars[i]) && m_rewriter.enum2bv().find(to_app(vars[i])->get_decl(), f)) { bvars.push_back(m.mk_const(f)); } @@ -128,7 +128,7 @@ public: // translate bit-vector consequences back to enumeration types for (unsigned i = 0; i < consequences.size(); ++i) { - expr* a, *b, *u, *v; + expr* a = 0, *b = 0, *u = 0, *v = 0; func_decl* f; rational num; unsigned bvsize; From 031d7e1b5992b50f30c4871031d695be48dff169 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 1 Jul 2017 16:58:40 -0700 Subject: [PATCH 101/159] use iterators, update build icon for osx Signed-off-by: Nikolaj Bjorner --- README.md | 2 +- src/smt/theory_seq.cpp | 15 +++++---------- src/util/scoped_vector.h | 25 +++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 465348dbd..0df1979a8 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z | Windows x86 | Windows x64 | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | TravisCI | | ----------- | ----------- | ---------- | ---------- | ---------- | --- | -------- | -![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | ![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) +![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | ![osx-badge](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) [1]: #building-z3-on-windows-using-visual-studio-command-prompt [2]: #building-z3-using-make-and-gccclang diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index dfb535f51..832995994 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -2246,10 +2246,7 @@ bool theory_seq::internalize_term(app* term) { return true; } TRACE("seq_verbose", tout << mk_pp(term, m) << "\n";); - unsigned num_args = term->get_num_args(); - expr* arg; - for (unsigned i = 0; i < num_args; i++) { - arg = term->get_arg(i); + for (expr* arg : *term) { mk_var(ensure_enode(arg)); } if (m.is_bool(term)) { @@ -2602,9 +2599,9 @@ void theory_seq::collect_statistics(::statistics & st) const { void theory_seq::init_model(expr_ref_vector const& es) { expr_ref new_s(m); - for (unsigned i = 0; i < es.size(); ++i) { + for (expr* e : es) { dependency* eqs = 0; - expr_ref s = canonize(es[i], eqs); + expr_ref s = canonize(e, eqs); if (is_var(s)) { new_s = m_factory->get_fresh_value(m.get_sort(s)); m_rep.update(s, new_s, eqs); @@ -2615,13 +2612,11 @@ void theory_seq::init_model(expr_ref_vector const& es) { void theory_seq::init_model(model_generator & mg) { m_factory = alloc(seq_factory, get_manager(), get_family_id(), mg.get_model()); mg.register_factory(m_factory); - for (unsigned j = 0; j < m_nqs.size(); ++j) { - ne const& n = m_nqs[j]; + for (ne const& n : m_nqs) { m_factory->register_value(n.l()); m_factory->register_value(n.r()); } - for (unsigned j = 0; j < m_nqs.size(); ++j) { - ne const& n = m_nqs[j]; + for (ne const& n : m_nqs) { for (unsigned i = 0; i < n.ls().size(); ++i) { init_model(n.ls(i)); init_model(n.rs(i)); diff --git a/src/util/scoped_vector.h b/src/util/scoped_vector.h index bacfbac89..f62fbc8a6 100644 --- a/src/util/scoped_vector.h +++ b/src/util/scoped_vector.h @@ -91,6 +91,31 @@ public: SASSERT(invariant()); } + class iterator { + scoped_vector const& m_vec; + unsigned m_index; + public: + iterator(scoped_vector const& v, unsigned idx): m_vec(v), m_index(idx) {} + + bool operator==(iterator const& other) const { return &other.m_vec == &m_vec && other.m_index == m_index; } + bool operator!=(iterator const& other) const { return &other.m_vec != &m_vec || other.m_index != m_index; } + T const& operator*() { return m_vec[m_index]; } + + iterator & operator++() { + ++m_index; + return *this; + } + + iterator operator++(int) { + iterator r = *this; + ++m_index; + return r; + } + }; + + iterator begin() { return iterator(*this, 0); } + iterator end() { return iterator(*this, m_size); } + void push_back(T const& t) { set_index(m_size, m_elems.size()); m_elems.push_back(t); From 934dd0db4af848dbe37c7af0f4df007978a247f1 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 1 Jul 2017 17:00:48 -0700 Subject: [PATCH 102/159] revert icon update Signed-off-by: Nikolaj Bjorner --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0df1979a8..465348dbd 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z | Windows x86 | Windows x64 | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | TravisCI | | ----------- | ----------- | ---------- | ---------- | ---------- | --- | -------- | -![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | ![osx-badge](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) +![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | ![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) [1]: #building-z3-on-windows-using-visual-studio-command-prompt [2]: #building-z3-using-make-and-gccclang From 416d955cfbd36a5f4aa4f42c29a927180da41367 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 1 Jul 2017 17:03:41 -0700 Subject: [PATCH 103/159] icon update, take 2 Signed-off-by: Nikolaj Bjorner --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 465348dbd..fa39f5a43 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z | Windows x86 | Windows x64 | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | TravisCI | | ----------- | ----------- | ---------- | ---------- | ---------- | --- | -------- | -![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | ![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) +![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | [![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) [1]: #building-z3-on-windows-using-visual-studio-command-prompt [2]: #building-z3-using-make-and-gccclang From cc4cc8e4fb3f7923b1c4f894126e70011a5b6cf0 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 1 Jul 2017 17:05:31 -0700 Subject: [PATCH 104/159] icon update, take 3 Signed-off-by: Nikolaj Bjorner --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fa39f5a43..4f8889caa 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z | Windows x86 | Windows x64 | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | TravisCI | | ----------- | ----------- | ---------- | ---------- | ---------- | --- | -------- | -![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | [![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) +[![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=4) | [![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge)]((https://cz3.visualstudio.com/Z3/_build/index?definitionId=7) | [![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge)]((https://cz3.visualstudio.com/Z3/_build/index?definitionId=3) | [![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=6) | [![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge)]((https://cz3.visualstudio.com/Z3/_build/index?definitionId=5) | [![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) [1]: #building-z3-on-windows-using-visual-studio-command-prompt [2]: #building-z3-using-make-and-gccclang From 47f194e4c981e6b438056f929d944d1191195cb3 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 1 Jul 2017 17:06:38 -0700 Subject: [PATCH 105/159] icon update, take 4 Signed-off-by: Nikolaj Bjorner --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4f8889caa..197928877 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z | Windows x86 | Windows x64 | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | TravisCI | | ----------- | ----------- | ---------- | ---------- | ---------- | --- | -------- | -[![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=4) | [![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge)]((https://cz3.visualstudio.com/Z3/_build/index?definitionId=7) | [![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge)]((https://cz3.visualstudio.com/Z3/_build/index?definitionId=3) | [![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=6) | [![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge)]((https://cz3.visualstudio.com/Z3/_build/index?definitionId=5) | [![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) +[![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=4) | [![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=7) | [![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=3) | [![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=6) | [![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=5) | [![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge)](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3) [1]: #building-z3-on-windows-using-visual-studio-command-prompt [2]: #building-z3-using-make-and-gccclang From 03fe3d74f88c14aba999703463e1d58f864f54a0 Mon Sep 17 00:00:00 2001 From: Murphy Berzish Date: Tue, 4 Jul 2017 13:28:18 -0400 Subject: [PATCH 106/159] clean up warnings in theory_str --- src/smt/theory_str.cpp | 112 +++++++++++++---------------------------- 1 file changed, 34 insertions(+), 78 deletions(-) diff --git a/src/smt/theory_str.cpp b/src/smt/theory_str.cpp index 0671c319c..d8d130212 100644 --- a/src/smt/theory_str.cpp +++ b/src/smt/theory_str.cpp @@ -232,11 +232,11 @@ namespace smt { for (unsigned i = 0; i < num_args; ++i) { enode * arg = e->get_arg(i); theory_var v_arg = mk_var(arg); - TRACE("str", tout << "arg has theory var #" << v_arg << std::endl;); + TRACE("str", tout << "arg has theory var #" << v_arg << std::endl;); (void)v_arg; } theory_var v = mk_var(e); - TRACE("str", tout << "term has theory var #" << v << std::endl;); + TRACE("str", tout << "term has theory var #" << v << std::endl;); (void)v; if (opt_EagerStringConstantLengthAssertions && u.str.is_string(term)) { TRACE("str", tout << "eagerly asserting length of string term " << mk_pp(term, m) << std::endl;); @@ -257,7 +257,7 @@ namespace smt { void theory_str::refresh_theory_var(expr * e) { enode * en = ensure_enode(e); - theory_var v = mk_var(en); + theory_var v = mk_var(en); (void)v; TRACE("str", tout << "refresh " << mk_pp(e, get_manager()) << ": v#" << v << std::endl;); m_basicstr_axiom_todo.push_back(en); } @@ -487,7 +487,6 @@ namespace smt { app * theory_str::mk_str_var(std::string name) { context & ctx = get_context(); - ast_manager & m = get_manager(); TRACE("str", tout << "creating string variable " << name << " at scope level " << sLevel << std::endl;); @@ -505,7 +504,7 @@ namespace smt { // this might help?? mk_var(ctx.get_enode(a)); m_basicstr_axiom_todo.push_back(ctx.get_enode(a)); - TRACE("str", tout << "add " << mk_pp(a, m) << " to m_basicstr_axiom_todo" << std::endl;); + TRACE("str", tout << "add " << mk_pp(a, get_manager()) << " to m_basicstr_axiom_todo" << std::endl;); variable_set.insert(a); internal_variable_set.insert(a); @@ -516,7 +515,6 @@ namespace smt { app * theory_str::mk_regex_rep_var() { context & ctx = get_context(); - ast_manager & m = get_manager(); sort * string_sort = u.str.mk_string_sort(); app * a = mk_fresh_const("regex", string_sort); @@ -527,7 +525,7 @@ namespace smt { SASSERT(ctx.e_internalized(a)); mk_var(ctx.get_enode(a)); m_basicstr_axiom_todo.push_back(ctx.get_enode(a)); - TRACE("str", tout << "add " << mk_pp(a, m) << " to m_basicstr_axiom_todo" << std::endl;); + TRACE("str", tout << "add " << mk_pp(a, get_manager()) << " to m_basicstr_axiom_todo" << std::endl;); variable_set.insert(a); //internal_variable_set.insert(a); @@ -933,8 +931,7 @@ namespace smt { SASSERT(len_xy); // build RHS: start by extracting x and y from Concat(x, y) - unsigned nArgs = a_cat->get_num_args(); - SASSERT(nArgs == 2); + SASSERT(a_cat->get_num_args() == 2); app * a_x = to_app(a_cat->get_arg(0)); app * a_y = to_app(a_cat->get_arg(1)); @@ -2054,7 +2051,7 @@ namespace smt { << "* |parent| = " << rational_to_string_if_exists(parentLen, parentLen_exists) << std::endl << "* |arg0| = " << rational_to_string_if_exists(arg0Len, arg0Len_exists) << std::endl << "* |arg1| = " << rational_to_string_if_exists(arg1Len, arg1Len_exists) << std::endl; - ); + ); (void)arg0Len_exists; if (parentLen_exists && !arg1Len_exists) { TRACE("str", tout << "make up len for arg1" << std::endl;); @@ -2125,7 +2122,8 @@ namespace smt { << "* |parent| = " << rational_to_string_if_exists(parentLen, parentLen_exists) << std::endl << "* |arg0| = " << rational_to_string_if_exists(arg0Len, arg0Len_exists) << std::endl << "* |arg1| = " << rational_to_string_if_exists(arg1Len, arg1Len_exists) << std::endl; - ); + ); (void)arg1Len_exists; + if (parentLen_exists && !arg0Len_exists) { TRACE("str", tout << "make up len for arg0" << std::endl;); expr_ref implyL11(m.mk_and(ctx.mk_eq_atom(mk_strlen(a_parent), mk_int(parentLen)), @@ -4496,8 +4494,6 @@ namespace smt { } void theory_str::process_unroll_eq_const_str(expr * unrollFunc, expr * constStr) { - ast_manager & m = get_manager(); - if (!u.re.is_unroll(to_app(unrollFunc))) { return; } @@ -4509,8 +4505,8 @@ namespace smt { zstring strValue; u.str.is_string(constStr, strValue); - TRACE("str", tout << "unrollFunc: " << mk_pp(unrollFunc, m) << std::endl - << "constStr: " << mk_pp(constStr, m) << std::endl;); + TRACE("str", tout << "unrollFunc: " << mk_pp(unrollFunc, get_manager()) << std::endl + << "constStr: " << mk_pp(constStr, get_manager()) << std::endl;); if (strValue == "") { return; @@ -4807,17 +4803,16 @@ namespace smt { bool theory_str::in_same_eqc(expr * n1, expr * n2) { if (n1 == n2) return true; context & ctx = get_context(); - ast_manager & m = get_manager(); // similar to get_eqc_value(), make absolutely sure // that we've set this up properly for the context if (!ctx.e_internalized(n1)) { - TRACE("str", tout << "WARNING: expression " << mk_ismt2_pp(n1, m) << " was not internalized" << std::endl;); + TRACE("str", tout << "WARNING: expression " << mk_ismt2_pp(n1, get_manager()) << " was not internalized" << std::endl;); ctx.internalize(n1, false); } if (!ctx.e_internalized(n2)) { - TRACE("str", tout << "WARNING: expression " << mk_ismt2_pp(n2, m) << " was not internalized" << std::endl;); + TRACE("str", tout << "WARNING: expression " << mk_ismt2_pp(n2, get_manager()) << " was not internalized" << std::endl;); ctx.internalize(n2, false); } @@ -4876,7 +4871,7 @@ namespace smt { expr * strAst = itor1->first; expr * substrAst = itor1->second; - expr * boolVar; + expr * boolVar = NULL; if (!contain_pair_bool_map.find(strAst, substrAst, boolVar)) { TRACE("str", tout << "warning: no entry for boolVar in contain_pair_bool_map" << std::endl;); } @@ -5013,7 +5008,7 @@ namespace smt { expr * strAst = itor1->first; expr * substrAst = itor1->second; - expr * boolVar; + expr * boolVar = NULL; if (!contain_pair_bool_map.find(strAst, substrAst, boolVar)) { TRACE("str", tout << "warning: no entry for boolVar in contain_pair_bool_map" << std::endl;); } @@ -5624,7 +5619,6 @@ namespace smt { } void theory_str::print_grounded_concat(expr * node, std::map, std::set > > & groundedMap) { - ast_manager & m = get_manager(); TRACE("str", tout << mk_pp(node, m) << std::endl;); if (groundedMap.find(node) != groundedMap.end()) { std::map, std::set >::iterator itor = groundedMap[node].begin(); @@ -5633,13 +5627,13 @@ namespace smt { tout << "\t[grounded] "; std::vector::const_iterator vIt = itor->first.begin(); for (; vIt != itor->first.end(); ++vIt) { - tout << mk_pp(*vIt, m) << ", "; + tout << mk_pp(*vIt, get_manager()) << ", "; } tout << std::endl; tout << "\t[condition] "; std::set::iterator sIt = itor->second.begin(); for (; sIt != itor->second.end(); sIt++) { - tout << mk_pp(*sIt, m) << ", "; + tout << mk_pp(*sIt, get_manager()) << ", "; } tout << std::endl; ); @@ -6935,7 +6929,7 @@ namespace smt { } void theory_str::more_value_tests(expr * valTester, zstring valTesterValue) { - ast_manager & m = get_manager(); + ast_manager & m = get_manager(); (void)m; expr * fVar = valueTester_fvar_map[valTester]; if (m_params.m_UseBinarySearch) { @@ -6990,17 +6984,16 @@ namespace smt { } bool theory_str::free_var_attempt(expr * nn1, expr * nn2) { - ast_manager & m = get_manager(); zstring nn2_str; if (internal_lenTest_vars.contains(nn1) && u.str.is_string(nn2, nn2_str)) { - TRACE("str", tout << "acting on equivalence between length tester var " << mk_ismt2_pp(nn1, m) - << " and constant " << mk_ismt2_pp(nn2, m) << std::endl;); + TRACE("str", tout << "acting on equivalence between length tester var " << mk_pp(nn1, get_manager()) + << " and constant " << mk_pp(nn2, get_manager()) << std::endl;); more_len_tests(nn1, nn2_str); return true; } else if (internal_valTest_vars.contains(nn1) && u.str.is_string(nn2, nn2_str)) { if (nn2_str == "more") { - TRACE("str", tout << "acting on equivalence between value var " << mk_ismt2_pp(nn1, m) - << " and constant " << mk_ismt2_pp(nn2, m) << std::endl;); + TRACE("str", tout << "acting on equivalence between value var " << mk_pp(nn1, get_manager()) + << " and constant " << mk_pp(nn2, get_manager()) << std::endl;); more_value_tests(nn1, nn2_str); } return true; @@ -7301,6 +7294,7 @@ namespace smt { // this might help?? theory_var v = mk_var(n); TRACE("str", tout << "variable " << mk_ismt2_pp(ap, get_manager()) << " is #" << v << std::endl;); + (void)v; } } } else if (ex_sort == bool_sort && !is_quantifier(ex)) { @@ -7387,7 +7381,6 @@ namespace smt { } void theory_str::init_search_eh() { - ast_manager & m = get_manager(); context & ctx = get_context(); TRACE("str", @@ -7395,7 +7388,7 @@ namespace smt { unsigned nFormulas = ctx.get_num_asserted_formulas(); for (unsigned i = 0; i < nFormulas; ++i) { expr * ex = ctx.get_asserted_formula(i); - tout << mk_ismt2_pp(ex, m) << (ctx.is_relevant(ex) ? " (rel)" : " (NOT REL)") << std::endl; + tout << mk_pp(ex, get_manager()) << (ctx.is_relevant(ex) ? " (rel)" : " (NOT REL)") << std::endl; } ); /* @@ -7410,36 +7403,6 @@ namespace smt { set_up_axioms(ex); } - /* - * Similar recursive descent, except over all initially assigned terms. - * This is done to find equalities between terms, etc. that we otherwise - * might not get a chance to see. - */ - - /* - expr_ref_vector assignments(m); - ctx.get_assignments(assignments); - for (expr_ref_vector::iterator i = assignments.begin(); i != assignments.end(); ++i) { - expr * ex = *i; - if (m.is_eq(ex)) { - TRACE("str", tout << "processing assignment " << mk_ismt2_pp(ex, m) << - ": expr is equality" << std::endl;); - app * eq = (app*)ex; - SASSERT(eq->get_num_args() == 2); - expr * lhs = eq->get_arg(0); - expr * rhs = eq->get_arg(1); - - enode * e_lhs = ctx.get_enode(lhs); - enode * e_rhs = ctx.get_enode(rhs); - std::pair eq_pair(e_lhs, e_rhs); - m_str_eq_todo.push_back(eq_pair); - } else { - TRACE("str", tout << "processing assignment " << mk_ismt2_pp(ex, m) - << ": expr ignored" << std::endl;); - } - } - */ - // this might be cheating but we need to make sure that certain maps are populated // before the first call to new_eq_eh() propagate(); @@ -7475,8 +7438,7 @@ namespace smt { } void theory_str::assign_eh(bool_var v, bool is_true) { - context & ctx = get_context(); - TRACE("str", tout << "assert: v" << v << " #" << ctx.bool_var2expr(v)->get_id() << " is_true: " << is_true << std::endl;); + TRACE("str", tout << "assert: v" << v << " #" << get_context().bool_var2expr(v)->get_id() << " is_true: " << is_true << std::endl;); } void theory_str::push_scope_eh() { @@ -7543,7 +7505,6 @@ namespace smt { void theory_str::pop_scope_eh(unsigned num_scopes) { sLevel -= num_scopes; TRACE("str", tout << "pop " << num_scopes << " to " << sLevel << std::endl;); - ast_manager & m = get_manager(); TRACE_CODE(if (is_trace_enabled("t_str_dump_assign_on_scope_change")) { dump_assignments(); }); @@ -7552,10 +7513,9 @@ namespace smt { obj_map >::iterator varItor = cut_var_map.begin(); while (varItor != cut_var_map.end()) { - expr * e = varItor->m_key; std::stack & val = cut_var_map[varItor->m_key]; while ((val.size() > 0) && (val.top()->level != 0) && (val.top()->level >= sLevel)) { - TRACE("str", tout << "remove cut info for " << mk_pp(e, m) << std::endl; print_cut_var(e, tout);); + TRACE("str", tout << "remove cut info for " << mk_pp(e, get_manager()) << std::endl; print_cut_var(e, tout);); // T_cut * aCut = val.top(); val.pop(); // dealloc(aCut); @@ -7577,8 +7537,7 @@ namespace smt { ptr_vector new_m_basicstr; for (ptr_vector::iterator it = m_basicstr_axiom_todo.begin(); it != m_basicstr_axiom_todo.end(); ++it) { enode * e = *it; - app * a = e->get_owner(); - TRACE("str", tout << "consider deleting " << mk_pp(a, get_manager()) + TRACE("str", tout << "consider deleting " << mk_pp(e->get_owner(), get_manager()) << ", enode scope level is " << e->get_iscope_lvl() << std::endl;); if (e->get_iscope_lvl() <= (unsigned)sLevel) { @@ -8861,7 +8820,7 @@ namespace smt { continue; } bool hasEqcValue = false; - expr * eqcString = get_eqc_value(itor->first, hasEqcValue); + get_eqc_value(itor->first, hasEqcValue); if (!hasEqcValue) { TRACE("str", tout << "found free variable " << mk_pp(itor->first, m) << std::endl;); needToAssignFreeVars = true; @@ -9104,7 +9063,6 @@ namespace smt { } void theory_str::print_value_tester_list(svector > & testerList) { - ast_manager & m = get_manager(); TRACE("str", int ss = testerList.size(); tout << "valueTesterList = {"; @@ -9113,7 +9071,7 @@ namespace smt { tout << std::endl; } tout << "(" << testerList[i].first << ", "; - tout << mk_ismt2_pp(testerList[i].second, m); + tout << mk_pp(testerList[i].second, get_manager()); tout << "), "; } tout << std::endl << "}" << std::endl; @@ -9345,8 +9303,7 @@ namespace smt { } bool anEqcHasValue = false; - // Z3_ast anEqc = get_eqc_value(t, aTester, anEqcHasValue); - expr * aTester_eqc_value = get_eqc_value(aTester, anEqcHasValue); + get_eqc_value(aTester, anEqcHasValue); if (!anEqcHasValue) { TRACE("str", tout << "value tester " << mk_ismt2_pp(aTester, m) << " doesn't have an equivalence class value." << std::endl;); @@ -9513,8 +9470,8 @@ namespace smt { items.reset(); rational low, high; - bool low_exists = lower_bound(cntInUnr, low); - bool high_exists = upper_bound(cntInUnr, high); + bool low_exists = lower_bound(cntInUnr, low); (void)low_exists; + bool high_exists = upper_bound(cntInUnr, high); (void)high_exists; TRACE("str", tout << "unroll " << mk_pp(unrFunc, mgr) << std::endl; @@ -10265,7 +10222,7 @@ namespace smt { } else { tout << "no eqc string constant"; } - tout << std::endl;); + tout << std::endl;); (void)effectiveInScope; if (effectiveLenInd == lenTesterInCbEq) { effectiveLenIndiStr = lenTesterValue; } else { @@ -10350,7 +10307,6 @@ namespace smt { void theory_str::process_free_var(std::map & freeVar_map) { context & ctx = get_context(); - ast_manager & m = get_manager(); std::set eqcRepSet; std::set leafVarSet; @@ -10377,7 +10333,7 @@ namespace smt { } } if (duplicated && dupVar != NULL) { - TRACE("str", tout << "Duplicated free variable found:" << mk_ismt2_pp(freeVar, m) + TRACE("str", tout << "Duplicated free variable found:" << mk_pp(freeVar, get_manager()) << " = " << mk_ismt2_pp(dupVar, m) << " (SKIP)" << std::endl;); continue; } else { From 253870c6d7bb13c508188c51d81002f048c70b51 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 4 Jul 2017 13:08:23 -0700 Subject: [PATCH 107/159] fix compiler warnings Signed-off-by: Nikolaj Bjorner --- src/muz/rel/dl_relation_manager.cpp | 50 +++++++------------ .../dl_mk_interp_tail_simplifier.cpp | 13 +++-- src/test/old_interval.cpp | 6 +-- src/test/small_object_allocator.cpp | 9 ++++ src/test/sorting_network.cpp | 10 ++-- src/test/substitution.cpp | 2 + src/util/total_order.h | 7 +-- src/util/uint_map.h | 5 ++ 8 files changed, 46 insertions(+), 56 deletions(-) diff --git a/src/muz/rel/dl_relation_manager.cpp b/src/muz/rel/dl_relation_manager.cpp index 9e02a764f..5bb47c5c3 100644 --- a/src/muz/rel/dl_relation_manager.cpp +++ b/src/muz/rel/dl_relation_manager.cpp @@ -36,13 +36,10 @@ namespace datalog { void relation_manager::reset_relations() { - relation_map::iterator it=m_relations.begin(); - relation_map::iterator end=m_relations.end(); - for(;it!=end;++it) { - func_decl * pred = it->m_key; + for (auto const& kv : m_relations) { + func_decl * pred = kv.m_key; get_context().get_manager().dec_ref(pred); //inc_ref in get_relation - relation_base * r=(*it).m_value; - r->deallocate(); + kv.m_value->deallocate(); } m_relations.reset(); } @@ -119,35 +116,25 @@ namespace datalog { } void relation_manager::collect_non_empty_predicates(decl_set & res) const { - relation_map::iterator it = m_relations.begin(); - relation_map::iterator end = m_relations.end(); - for(; it!=end; ++it) { - if(!it->m_value->fast_empty()) { - res.insert(it->m_key); + for (auto const& kv : m_relations) { + if (!kv.m_value->fast_empty()) { + res.insert(kv.m_key); } } } void relation_manager::restrict_predicates(const decl_set & preds) { - typedef ptr_vector fd_vector; - fd_vector to_remove; + ptr_vector to_remove; - relation_map::iterator rit = m_relations.begin(); - relation_map::iterator rend = m_relations.end(); - for(; rit!=rend; ++rit) { - func_decl * pred = rit->m_key; + for (auto const& kv : m_relations) { + func_decl* pred = kv.m_key; if (!preds.contains(pred)) { to_remove.insert(pred); } } - fd_vector::iterator pit = to_remove.begin(); - fd_vector::iterator pend = to_remove.end(); - for(; pit!=pend; ++pit) { - func_decl * pred = *pit; - relation_base * rel; - VERIFY( m_relations.find(pred, rel) ); - rel->deallocate(); + for (func_decl* pred : to_remove) { + m_relations.find(pred)->deallocate(); m_relations.remove(pred); get_context().get_manager().dec_ref(pred); } @@ -283,11 +270,9 @@ namespace datalog { } table_plugin * relation_manager::get_table_plugin(symbol const& k) { - table_plugin_vector::iterator tpit = m_table_plugins.begin(); - table_plugin_vector::iterator tpend = m_table_plugins.end(); - for(; tpit!=tpend; ++tpit) { - if((*tpit)->get_name()==k) { - return *tpit; + for (table_plugin * tp : m_table_plugins) { + if (tp->get_name()==k) { + return tp; } } return 0; @@ -341,10 +326,9 @@ namespace datalog { return res; } - for (unsigned i = 0; i < m_relation_plugins.size(); ++i) { - p = m_relation_plugins[i]; - if (p->can_handle_signature(s)) { - return p->mk_empty(s); + for (relation_plugin* p1 : m_relation_plugins) { + if (p1->can_handle_signature(s)) { + return p1->mk_empty(s); } } diff --git a/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp b/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp index 3c1d1b924..1ed847e89 100644 --- a/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp +++ b/src/muz/transforms/dl_mk_interp_tail_simplifier.cpp @@ -250,7 +250,7 @@ namespace datalog { bool detect_equivalences(expr_ref_vector& v, bool inside_disjunction) { bool have_pair = false; - unsigned prev_pair_idx; + unsigned prev_pair_idx = 0; arg_pair ap; unsigned read_idx = 0; @@ -296,21 +296,20 @@ namespace datalog { br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { - if (m.is_not(f) && (m.is_and(args[0]) || m.is_or(args[0]))) { - SASSERT(num==1); + SASSERT(num == 1); expr_ref tmp(m); app* a = to_app(args[0]); m_app_args.reset(); - for (unsigned i = 0; i < a->get_num_args(); ++i) { - m_brwr.mk_not(a->get_arg(i), tmp); + for (expr* arg : *a) { + m_brwr.mk_not(arg, tmp); m_app_args.push_back(tmp); } if (m.is_and(args[0])) { - result = m.mk_or(m_app_args.size(), m_app_args.c_ptr()); + result = mk_or(m_app_args); } else { - result = m.mk_and(m_app_args.size(), m_app_args.c_ptr()); + result = mk_and(m_app_args); } return BR_REWRITE2; } diff --git a/src/test/old_interval.cpp b/src/test/old_interval.cpp index 92064c03e..12a45555d 100644 --- a/src/test/old_interval.cpp +++ b/src/test/old_interval.cpp @@ -120,9 +120,9 @@ class interval_tester { interval singleton(int i) { return interval(m, rational(i)); } interval all() { return interval(m); } - interval l(int i, bool o = false, int idx = 0) { return interval(m, rational(i), o, true, idx == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx))); } - interval r(int i, bool o = false, int idx = 0) { return interval(m, rational(i), o, false, idx == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx))); } - interval b(int l, int u, bool lo = false, bool uo = false, int idx_l = 0, int idx_u = 0) { + interval l(int i, bool o = false, size_t idx = 0) { return interval(m, rational(i), o, true, idx == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx))); } + interval r(int i, bool o = false, size_t idx = 0) { return interval(m, rational(i), o, false, idx == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx))); } + interval b(int l, int u, bool lo = false, bool uo = false, size_t idx_l = 0, size_t idx_u = 0) { return interval(m, rational(l), lo, idx_l == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx_l)), rational(u), uo, idx_u == 0 ? 0 : m.mk_leaf(reinterpret_cast(idx_u))); } diff --git a/src/test/small_object_allocator.cpp b/src/test/small_object_allocator.cpp index 1ecf865dd..5ae2836d0 100644 --- a/src/test/small_object_allocator.cpp +++ b/src/test/small_object_allocator.cpp @@ -36,5 +36,14 @@ void tst_small_object_allocator() { r3 = new (soa) char[1]; TRACE("small_object_allocator", tout << "r1: " << (void*)r1 << " r2: " << (void*)r2 << " r3: " << (void*)r3 << " r4: " << (void*)r4 << "\n";); + (void)r1; + (void)r2; + (void)r3; + (void)r4; + (void)q1; + + (void)p1; + (void)p2; + (void)p3; } diff --git a/src/test/sorting_network.cpp b/src/test/sorting_network.cpp index 81340651a..87cc05375 100644 --- a/src/test/sorting_network.cpp +++ b/src/test/sorting_network.cpp @@ -364,15 +364,13 @@ void test_at_most_1(unsigned n, bool full) { for (unsigned i = 0; i < ext.m_clauses.size(); ++i) { solver.assert_expr(ext.m_clauses[i].get()); } - lbool res; if (full) { solver.push(); solver.assert_expr(m.mk_not(m.mk_eq(result1, result2))); std::cout << result1 << "\n"; - res = solver.check(); - SASSERT(res == l_false); + VERIFY(l_false == solver.check()); solver.pop(1); } @@ -390,8 +388,7 @@ void test_at_most_1(unsigned n, bool full) { std::cout << atom << "\n"; if (is_true) ++k; } - res = solver.check(); - SASSERT(res == l_true); + VERIFY(l_false == solver.check()); if (k > 1) { solver.assert_expr(result1); } @@ -402,8 +399,7 @@ void test_at_most_1(unsigned n, bool full) { else { solver.assert_expr(m.mk_not(result1)); } - res = solver.check(); - SASSERT(res == l_false); + VERIFY(l_false == solver.check()); solver.pop(1); } } diff --git a/src/test/substitution.cpp b/src/test/substitution.cpp index cdc7f2080..5609225c6 100644 --- a/src/test/substitution.cpp +++ b/src/test/substitution.cpp @@ -35,6 +35,8 @@ void tst_substitution() bool ok1 = unif(v1.get(), v2.get(), subst, false); bool ok2 = unif(v2.get(), v1.get(), subst, false); + (void)ok1; + (void)ok2; expr_ref res(m); diff --git a/src/util/total_order.h b/src/util/total_order.h index 7238a5ef9..6fda88110 100644 --- a/src/util/total_order.h +++ b/src/util/total_order.h @@ -79,12 +79,7 @@ class total_order { } cell * to_cell(T const & a) const { - void * r; -#ifdef Z3DEBUG - bool ok = -#endif - m_map.find(a, r); - SASSERT(ok); + void * r = m_map.find(a); return reinterpret_cast(r); } diff --git a/src/util/uint_map.h b/src/util/uint_map.h index 13e0a9db3..0344de322 100644 --- a/src/util/uint_map.h +++ b/src/util/uint_map.h @@ -38,6 +38,11 @@ public: return v != 0; } } + + T * find(unsigned k) const { + SASSERT(k < m_map.size() && m_map[k] != 0); + return m_map[k]; + } void insert(unsigned k, T * v) { m_map.reserve(k+1); From a1306eaab6497f1a321b97e8fc1d6463edcf7890 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 4 Jul 2017 13:17:37 -0700 Subject: [PATCH 108/159] fix compiler warnings Signed-off-by: Nikolaj Bjorner --- src/test/ext_numeral.cpp | 3 +-- src/test/heap.cpp | 5 +++-- src/test/karr.cpp | 4 ++-- src/test/model_based_opt.cpp | 4 +++- src/test/model_evaluator.cpp | 1 - src/test/mpz.cpp | 2 ++ src/test/object_allocator.cpp | 1 + src/test/qe_arith.cpp | 4 ++-- 8 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/test/ext_numeral.cpp b/src/test/ext_numeral.cpp index 0e2b691c9..6f92b1372 100644 --- a/src/test/ext_numeral.cpp +++ b/src/test/ext_numeral.cpp @@ -158,8 +158,7 @@ static void FUN_NAME(int a, ext_numeral_kind ak, int b, ext_numeral_kind bk, boo scoped_mpq _a(m), _b(m); \ m.set(_a, a); \ m.set(_b, b); \ - bool r = OP_NAME(m, _a, ak, _b, bk); \ - SASSERT(r == expected); \ + VERIFY(expected == OP_NAME(m, _a, ak, _b, bk)); \ } #define MK_TST_REL(NAME) MK_TST_REL_CORE(tst_ ## NAME, NAME) diff --git a/src/test/heap.cpp b/src/test/heap.cpp index e745463ff..3d5c5308a 100644 --- a/src/test/heap.cpp +++ b/src/test/heap.cpp @@ -47,12 +47,13 @@ static void tst1() { for (; it != end; ++it) { SASSERT(h.contains(*it)); } - int last = -1; while (!h.empty()) { int m1 = h.min_value(); int m2 = h.erase_min(); + (void)m1; + (void)m2; SASSERT(m1 == m2); - SASSERT(last < m2); + SASSERT(-1 < m2); } } diff --git a/src/test/karr.cpp b/src/test/karr.cpp index c5581cc66..c69932e22 100644 --- a/src/test/karr.cpp +++ b/src/test/karr.cpp @@ -58,7 +58,7 @@ namespace karr { } lbool is_sat = hb.saturate(); hb.display(std::cout); - SASSERT(is_sat == l_true); + VERIFY(is_sat == l_true); dst.reset(); unsigned basis_size = hb.get_basis_size(); for (unsigned i = 0; i < basis_size; ++i) { @@ -85,7 +85,7 @@ namespace karr { } lbool is_sat = hb.saturate(); hb.display(std::cout); - SASSERT(is_sat == l_true); + VERIFY(is_sat == l_true); dst.reset(); unsigned basis_size = hb.get_basis_size(); bool first_initial = true; diff --git a/src/test/model_based_opt.cpp b/src/test/model_based_opt.cpp index 64b2df285..5ee671a4a 100644 --- a/src/test/model_based_opt.cpp +++ b/src/test/model_based_opt.cpp @@ -20,6 +20,7 @@ static void add_ineq(opt::model_based_opt& mbo, mbo.add_constraint(vars, rational(k), rel); } +#if 0 static void add_ineq(opt::model_based_opt& mbo, unsigned x, int a, unsigned y, int b, @@ -31,6 +32,7 @@ static void add_ineq(opt::model_based_opt& mbo, vars.push_back(var(z, rational(c))); mbo.add_constraint(vars, rational(k), rel); } +#endif static void add_random_ineq(opt::model_based_opt& mbo, random_gen& r, @@ -295,7 +297,7 @@ static void test8() { unsigned z = mbo.add_var(rational(4)); unsigned u = mbo.add_var(rational(5)); unsigned v = mbo.add_var(rational(6)); - unsigned w = mbo.add_var(rational(6)); + // unsigned w = mbo.add_var(rational(6)); add_ineq(mbo, x0, 1, y, -1, 0, opt::t_le); add_ineq(mbo, x, 1, y, -1, 0, opt::t_lt); diff --git a/src/test/model_evaluator.cpp b/src/test/model_evaluator.cpp index 0b509fba6..00048b230 100644 --- a/src/test/model_evaluator.cpp +++ b/src/test/model_evaluator.cpp @@ -28,7 +28,6 @@ void tst_model_evaluator() { expr_ref vB2(m.mk_var(2, m.mk_bool_sort()), m); expr* vI0p = vI0.get(); expr* vI1p = vI1.get(); - expr* vB0p = vB0.get(); expr* vB1p = vB1.get(); expr* vB2p = vB2.get(); diff --git a/src/test/mpz.cpp b/src/test/mpz.cpp index ee7cf39f1..02627e842 100644 --- a/src/test/mpz.cpp +++ b/src/test/mpz.cpp @@ -147,6 +147,7 @@ void tst_div2k(synch_mpz_manager & m, mpz const & v, unsigned k) { m.power(two, k, pw); m.machine_div(v, pw, y); bool is_eq = m.eq(x, y); + (void)is_eq; CTRACE("mpz_2k", !is_eq, tout << "div: " << m.to_string(v) << ", k: " << k << " r: " << m.to_string(x) << ", expected: " << m.to_string(y) << "\n";); SASSERT(is_eq); m.del(x); @@ -174,6 +175,7 @@ void tst_mul2k(synch_mpz_manager & m, mpz const & v, unsigned k) { m.power(two, k, pw); m.mul(v, pw, y); bool is_eq = m.eq(x, y); + (void)is_eq; CTRACE("mpz_2k", !is_eq, tout << "mul: " << m.to_string(v) << ", k: " << k << " r: " << m.to_string(x) << ", expected: " << m.to_string(y) << "\n";); SASSERT(is_eq); m.del(x); diff --git a/src/test/object_allocator.cpp b/src/test/object_allocator.cpp index 16b9331e2..cca42cf6f 100644 --- a/src/test/object_allocator.cpp +++ b/src/test/object_allocator.cpp @@ -61,6 +61,7 @@ static void tst1() { m.recycle(c1); cell * c3 = m.allocate(); + (void)c3; SASSERT(c3->m_coeff.is_zero()); } diff --git a/src/test/qe_arith.cpp b/src/test/qe_arith.cpp index a73f7ed38..a52c02ecb 100644 --- a/src/test/qe_arith.cpp +++ b/src/test/qe_arith.cpp @@ -163,7 +163,7 @@ static app_ref generate_ineqs(ast_manager& m, sort* s, vector& app* x = vars[0].get(); app* y = vars[1].get(); - app* z = vars[2].get(); + // app* z = vars[2].get(); // // ax <= by, ax < by, not (ax >= by), not (ax > by) // @@ -247,7 +247,7 @@ static void test2(char const *ex) { ctx.push(); ctx.assert_expr(fml); lbool result = ctx.check(); - SASSERT(result == l_true); + VERIFY(result == l_true); ref md; ctx.get_model(md); ctx.pop(1); From d66db280a875f5f646b61a0ee0f41f8bf2877d97 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 4 Jul 2017 13:43:32 -0700 Subject: [PATCH 109/159] fix compiler warnings Signed-off-by: Nikolaj Bjorner --- src/ast/substitution/substitution.cpp | 4 ++-- src/tactic/arith/elim01_tactic.cpp | 2 +- src/tactic/arith/lia2card_tactic.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ast/substitution/substitution.cpp b/src/ast/substitution/substitution.cpp index eea1938a6..f741d3fd4 100644 --- a/src/ast/substitution/substitution.cpp +++ b/src/ast/substitution/substitution.cpp @@ -85,7 +85,7 @@ void substitution::apply(unsigned num_actual_offsets, unsigned const * deltas, e m_state = APPLY; unsigned j; - expr * e; + expr * e = 0; unsigned off; expr_offset n1; bool visited; @@ -214,7 +214,7 @@ void substitution::apply(unsigned num_actual_offsets, unsigned const * deltas, e } } SASSERT(m_apply_cache.contains(n)); - m_apply_cache.find(n, e); + VERIFY(m_apply_cache.find(n, e)); m_new_exprs.push_back(e); result = e; diff --git a/src/tactic/arith/elim01_tactic.cpp b/src/tactic/arith/elim01_tactic.cpp index 1aef52d78..e00b1e9c0 100644 --- a/src/tactic/arith/elim01_tactic.cpp +++ b/src/tactic/arith/elim01_tactic.cpp @@ -169,7 +169,7 @@ public: for (; bit != bend; ++bit) { if (!is_app(*bit)) continue; app* x = to_app(*bit); - bool s1, s2; + bool s1 = false, s2 = false; rational lo, hi; if (a.is_int(x) && bounds.has_lower(x, lo, s1) && !s1 && zero <= lo && diff --git a/src/tactic/arith/lia2card_tactic.cpp b/src/tactic/arith/lia2card_tactic.cpp index 4c2e0dead..8f37a8d5e 100644 --- a/src/tactic/arith/lia2card_tactic.cpp +++ b/src/tactic/arith/lia2card_tactic.cpp @@ -176,7 +176,7 @@ public: bound_manager::iterator bit = bounds.begin(), bend = bounds.end(); for (; bit != bend; ++bit) { expr* x = *bit; - bool s1, s2; + bool s1 = false, s2 = false; rational lo, hi; if (a.is_int(x) && bounds.has_lower(x, lo, s1) && !s1 && lo.is_zero() && From bd92797663eb29f92163249e92f4f80fe15bc5f2 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 4 Jul 2017 15:25:59 -0700 Subject: [PATCH 110/159] fix compiler warnings Signed-off-by: Nikolaj Bjorner --- src/test/bit_vector.cpp | 2 +- src/test/bv_simplifier_plugin.cpp | 58 +++++++++++++++---------------- src/test/check_assumptions.cpp | 2 +- src/test/dl_context.cpp | 54 +++++++++++++++------------- src/test/dl_query.cpp | 2 +- src/test/heap.cpp | 1 + src/test/hwf.cpp | 6 ++-- src/test/list.cpp | 1 + src/test/mpff.cpp | 2 +- src/test/nlsat.cpp | 3 +- src/test/pb2bv.cpp | 8 ++--- src/test/polynorm.cpp | 1 + src/test/proof_checker.cpp | 4 +-- src/test/rational.cpp | 2 +- src/test/sat_user_scope.cpp | 1 + src/test/simple_parser.cpp | 1 + src/test/upolynomial.cpp | 12 +++---- 17 files changed, 83 insertions(+), 77 deletions(-) diff --git a/src/test/bit_vector.cpp b/src/test/bit_vector.cpp index 7d3f96ae4..6f83bb328 100644 --- a/src/test/bit_vector.cpp +++ b/src/test/bit_vector.cpp @@ -48,7 +48,7 @@ static void tst1() { SASSERT(v1.size() == v2.size()); if (v1.size() > 0) { unsigned idx = rand()%v1.size(); - SASSERT(v1.get(idx) == v2[idx]); + VERIFY(v1.get(idx) == v2[idx]); } } else if (op <= 5) { diff --git a/src/test/bv_simplifier_plugin.cpp b/src/test/bv_simplifier_plugin.cpp index dc930bb82..69b97a9cc 100644 --- a/src/test/bv_simplifier_plugin.cpp +++ b/src/test/bv_simplifier_plugin.cpp @@ -133,7 +133,7 @@ public: params[0] = parameter(2); ar = m_manager.mk_app(m_fid, OP_REPEAT, 1, params, 1, es); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((a64 << 32) | a64) == u64(e.get())); + VERIFY(((a64 << 32) | a64) == u64(e.get())); ar = m_manager.mk_app(m_fid, OP_BREDOR, e1.get()); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); @@ -163,11 +163,11 @@ public: ar = m_manager.mk_app(m_fid, OP_BIT0); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(!bit2bool(e.get())); + VERIFY(!bit2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_BIT1); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(bit2bool(e.get())); + VERIFY(bit2bool(e.get())); } @@ -187,113 +187,113 @@ public: ar = m_manager.mk_app(m_fid, OP_BADD, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a + b) == u32(e.get())); + VERIFY((a + b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BSUB, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a - b) == u32(e.get())); + VERIFY((a - b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BMUL, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a * b) == u32(e.get())); + VERIFY((a * b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BAND, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a & b) == u32(e.get())); + VERIFY((a & b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BOR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a | b) == u32(e.get())); + VERIFY((a | b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BNOR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(~(a | b) == u32(e.get())); + VERIFY(~(a | b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BXOR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a ^ b) == u32(e.get())); + VERIFY((a ^ b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BXNOR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((~(a ^ b)) == u32(e.get())); + VERIFY((~(a ^ b)) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BNAND, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((~(a & b)) == u32(e.get())); + VERIFY((~(a & b)) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_ULEQ, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a <= b) == ast2bool(e.get())); + VERIFY((a <= b) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_UGEQ, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a >= b) == ast2bool(e.get())); + VERIFY((a >= b) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_ULT, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a < b) == ast2bool(e.get())); + VERIFY((a < b) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_UGT, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a > b) == ast2bool(e.get())); + VERIFY((a > b) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_SLEQ, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((sa <= sb) == ast2bool(e.get())); + VERIFY((sa <= sb) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_SGEQ, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((sa >= sb) == ast2bool(e.get())); + VERIFY((sa >= sb) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_SLT, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((sa < sb) == ast2bool(e.get())); + VERIFY((sa < sb) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_SGT, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((sa > sb) == ast2bool(e.get())); + VERIFY((sa > sb) == ast2bool(e.get())); ar = m_manager.mk_app(m_fid, OP_BSHL, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((b>=32)?0:(a << b)) == u32(e.get())); + VERIFY(((b>=32)?0:(a << b)) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BLSHR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((b>=32)?0:(a >> b)) == u32(e.get())); + VERIFY(((b>=32)?0:(a >> b)) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BASHR, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); std::cout << "compare: " << sa << " >> " << b << " = " << (sa >> b) << " with " << i32(e.get()) << "\n"; - SASSERT(b >= 32 || ((sa >> b) == i32(e.get()))); + VERIFY(b >= 32 || ((sa >> b) == i32(e.get()))); if (b != 0) { ar = m_manager.mk_app(m_fid, OP_BSDIV, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((sa / sb) == i32(e.get())); + VERIFY((sa / sb) == i32(e.get())); ar = m_manager.mk_app(m_fid, OP_BUDIV, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a / b) == u32(e.get())); + VERIFY((a / b) == u32(e.get())); ar = m_manager.mk_app(m_fid, OP_BSREM, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - //SASSERT((sa % sb) == i32(e.get())); + //VERIFY((sa % sb) == i32(e.get())); ar = m_manager.mk_app(m_fid, OP_BUREM, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a % b) == u32(e.get())); + VERIFY((a % b) == u32(e.get())); // TBD: BSMOD. } ar = m_manager.mk_app(m_fid, OP_CONCAT, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT(((a64 << 32) | b64) == u64(e.get())); + VERIFY(((a64 << 32) | b64) == u64(e.get())); ar = m_manager.mk_app(m_fid, OP_BCOMP, 2, e1e2); m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); - SASSERT((a == b) == bit2bool(e.get())); + VERIFY((a == b) == bit2bool(e.get())); } void test() { diff --git a/src/test/check_assumptions.cpp b/src/test/check_assumptions.cpp index fa8327cd4..918513ca0 100644 --- a/src/test/check_assumptions.cpp +++ b/src/test/check_assumptions.cpp @@ -38,7 +38,7 @@ void tst_check_assumptions() expr * npE = np.get(); lbool res1 = ctx.check(1, &npE); - SASSERT(res1==l_true); + VERIFY(res1 == l_true); ctx.assert_expr(npE); diff --git a/src/test/dl_context.cpp b/src/test/dl_context.cpp index ac09722ac..99a0480a6 100644 --- a/src/test/dl_context.cpp +++ b/src/test/dl_context.cpp @@ -14,6 +14,35 @@ Copyright (c) 2015 Microsoft Corporation using namespace datalog; +void tst_dl_context() { + symbol relations[] = { symbol("tr_skip"), symbol("tr_sparse"), symbol("tr_hashtable"), symbol("smt_relation2") }; + + return; + +#if 0 + const unsigned rel_cnt = sizeof(relations)/sizeof(symbol); + const char * test_file = "c:\\tvm\\src\\benchmarks\\datalog\\t0.datalog"; + + params_ref params; + for(unsigned rel_index=0; rel_index=0; eager_checking--) { + params.set_bool("eager_emptiness_checking", eager_checking!=0); + + std::cerr << "Testing " << relations[rel_index] << "\n"; + std::cerr << "Eager emptiness checking " << (eager_checking!=0 ? "on" : "off") << "\n"; + dl_context_simple_query_test(params); + dl_context_saturate_file(params, test_file); + } + } +#endif + +} + + +#if 0 + + static lbool dl_context_eval_unary_predicate(ast_manager & m, context & ctx, char const* problem_text, const char * pred_name) { parser* p = parser::create(ctx,m); @@ -72,29 +101,4 @@ void dl_context_saturate_file(params_ref & params, const char * f) { ctx.get_rel_context()->saturate(); std::cerr << "Done\n"; } - -void tst_dl_context() { - symbol relations[] = { symbol("tr_skip"), symbol("tr_sparse"), symbol("tr_hashtable"), symbol("smt_relation2") }; - const unsigned rel_cnt = sizeof(relations)/sizeof(symbol); - - return; -#if 0 - const char * test_file = "c:\\tvm\\src\\benchmarks\\datalog\\t0.datalog"; - - params_ref params; - for(unsigned rel_index=0; rel_index=0; eager_checking--) { - params.set_bool("eager_emptiness_checking", eager_checking!=0); - - std::cerr << "Testing " << relations[rel_index] << "\n"; - std::cerr << "Eager emptiness checking " << (eager_checking!=0 ? "on" : "off") << "\n"; - dl_context_simple_query_test(params); - dl_context_saturate_file(params, test_file); - } - } #endif -} - - - diff --git a/src/test/dl_query.cpp b/src/test/dl_query.cpp index ae7313e41..e69f1fb13 100644 --- a/src/test/dl_query.cpp +++ b/src/test/dl_query.cpp @@ -40,7 +40,7 @@ void dl_query_ask_for_last_arg(context & ctx, func_decl * pred, relation_fact & lbool is_sat = ctx.query(query); std::cerr << "@@ last arg query should succeed: " << should_be_successful << "\n"; - SASSERT(is_sat != l_undef); + VERIFY(is_sat != l_undef); relation_fact res_fact(m); res_fact.push_back(f.back()); diff --git a/src/test/heap.cpp b/src/test/heap.cpp index 3d5c5308a..17f9cfaa0 100644 --- a/src/test/heap.cpp +++ b/src/test/heap.cpp @@ -77,6 +77,7 @@ static void dump_heap(const int_heap2 & h, std::ostream & out) { } static void tst2() { + (void)dump_heap; int_heap2 h(N); for (int i = 0; i < N * 10; i++) { if (i % 1000 == 0) std::cout << "i: " << i << std::endl; diff --git a/src/test/hwf.cpp b/src/test/hwf.cpp index be32b5400..7a030a452 100644 --- a/src/test/hwf.cpp +++ b/src/test/hwf.cpp @@ -44,19 +44,19 @@ static void bug_to_rational() { unsynch_mpq_manager mq; scoped_mpq r(mq); - double ad, rd; + double ad = 0, rd = 0; m.set(a, 0.0); m.to_rational(a, r); ad = m.to_double(a); rd = mq.get_double(r); - SASSERT(ad == rd); + VERIFY(ad == rd); m.set(a, 1.0); m.to_rational(a, r); ad = m.to_double(a); rd = mq.get_double(r); - SASSERT(ad == rd); + VERIFY(ad == rd); m.set(a, 1.5); m.to_rational(a, r); diff --git a/src/test/list.cpp b/src/test/list.cpp index 5672f4246..a7ad76972 100644 --- a/src/test/list.cpp +++ b/src/test/list.cpp @@ -35,6 +35,7 @@ static void tst1() { list * l5 = append(r, l4, l2); TRACE("list", display(tout, l5->begin(), l5->end()); tout << "\n";); list * l6 = append(r, l5, l5); + (void) l6; TRACE("list", display(tout, l6->begin(), l6->end()); tout << "\n";); } diff --git a/src/test/mpff.cpp b/src/test/mpff.cpp index 44930f2bd..ca2354b8b 100644 --- a/src/test/mpff.cpp +++ b/src/test/mpff.cpp @@ -435,7 +435,7 @@ static void tst_limits(unsigned prec) { bool overflow = false; try { m.inc(a); } catch (mpff_manager::overflow_exception) { overflow = true; } - SASSERT(overflow); + VERIFY(overflow); m.set_max(a); m.dec(a); SASSERT(m.eq(a, b)); diff --git a/src/test/nlsat.cpp b/src/test/nlsat.cpp index 27a0aa1da..df25db927 100644 --- a/src/test/nlsat.cpp +++ b/src/test/nlsat.cpp @@ -391,7 +391,6 @@ static void tst7() { params_ref ps; reslimit rlim; nlsat::solver s(rlim, ps); - anum_manager & am = s.am(); nlsat::pmanager & pm = s.pm(); nlsat::var x0, x1, x2, a, b, c, d; a = s.mk_var(false); @@ -423,7 +422,7 @@ static void tst7() { nlsat::literal_vector litsv(lits.size(), lits.c_ptr()); lbool res = s.check(litsv); - SASSERT(res == l_false); + VERIFY(res == l_false); for (unsigned i = 0; i < litsv.size(); ++i) { s.display(std::cout, litsv[i]); std::cout << " "; diff --git a/src/test/pb2bv.cpp b/src/test/pb2bv.cpp index c114997c5..fcc309883 100644 --- a/src/test/pb2bv.cpp +++ b/src/test/pb2bv.cpp @@ -83,10 +83,10 @@ static void test_semantics(ast_manager& m, expr_ref_vector const& vars, vectorcheck_sat(0,0); - SASSERT(res == l_true); + VERIFY(res == l_true); slv->assert_expr(m.is_true(result2) ? m.mk_not(result1) : result1.get()); res = slv->check_sat(0,0); - SASSERT(res == l_false); + VERIFY(res == l_false); } } diff --git a/src/test/polynorm.cpp b/src/test/polynorm.cpp index a8f4ab861..0bc9dfe3c 100644 --- a/src/test/polynorm.cpp +++ b/src/test/polynorm.cpp @@ -88,6 +88,7 @@ private: expr_ref_vector& factors = poly.factors(); expr_ref_vector& coefficients = poly.coefficients(); expr_ref& coefficient = poly.coefficient(); + (void) coefficient; m_rw(term); diff --git a/src/test/proof_checker.cpp b/src/test/proof_checker.cpp index 7f9827187..035326b26 100644 --- a/src/test/proof_checker.cpp +++ b/src/test/proof_checker.cpp @@ -11,7 +11,6 @@ void tst_checker1() { ast_manager m(PGM_FINE); expr_ref a(m); proof_ref p1(m), p2(m), p3(m), p4(m); - bool result; expr_ref_vector side_conditions(m); a = m.mk_const(symbol("a"), m.mk_bool_sort()); @@ -26,8 +25,7 @@ void tst_checker1() { proof_checker checker(m); p4 = m.mk_lemma(p3.get(), m.mk_or(a.get(), m.mk_not(a.get()))); ast_ll_pp(std::cout, m, p4.get()); - result = checker.check(p4.get(), side_conditions); - SASSERT(result); + VERIFY(checker.check(p4.get(), side_conditions)); } void tst_proof_checker() { diff --git a/src/test/rational.cpp b/src/test/rational.cpp index 834aab92f..ac478af98 100644 --- a/src/test/rational.cpp +++ b/src/test/rational.cpp @@ -196,7 +196,7 @@ static void tst2() { // get_int64, get_uint64 uint64 u1 = uint64_max.get_uint64(); uint64 u2 = UINT64_MAX; - SASSERT(u1 == u2); + VERIFY(u1 == u2); std::cout << "int64_max: " << int64_max << ", INT64_MAX: " << INT64_MAX << ", int64_max.get_int64(): " << int64_max.get_int64() << ", int64_max.get_uint64(): " << int64_max.get_uint64() << "\n"; SASSERT(int64_max.get_int64() == INT64_MAX); SASSERT(int64_min.get_int64() == INT64_MIN); diff --git a/src/test/sat_user_scope.cpp b/src/test/sat_user_scope.cpp index aa717f371..54de5976a 100644 --- a/src/test/sat_user_scope.cpp +++ b/src/test/sat_user_scope.cpp @@ -35,6 +35,7 @@ static void add_clause(sat::solver& s, random_gen& r, trail_t& t) { } static void display_state(std::ostream& out, sat::solver& s, trail_t& t) { + (void)t; s.display(out); } diff --git a/src/test/simple_parser.cpp b/src/test/simple_parser.cpp index a5d4d8def..934552711 100644 --- a/src/test/simple_parser.cpp +++ b/src/test/simple_parser.cpp @@ -38,6 +38,7 @@ void tst_simple_parser() { TRACE("simple_parser", tout << mk_pp(r, m) << "\n";); p.parse_string("(+ x (* y x) x)", r); float vals[2] = { 2.0f, 3.0f }; + (void)vals; TRACE("simple_parser", tout << mk_pp(r, m) << "\n"; tout << "val: " << eval(r, 2, vals) << "\n";); diff --git a/src/test/upolynomial.cpp b/src/test/upolynomial.cpp index e7dcf2719..3d9815873 100644 --- a/src/test/upolynomial.cpp +++ b/src/test/upolynomial.cpp @@ -129,18 +129,18 @@ static void tst_isolate_roots(polynomial_ref const & p, unsigned prec, mpbq_mana tout << "fourier upper: " << um.sign_variations_at(fseq, uppers[i]) << "\n";); unsigned fsv_lower = um.sign_variations_at(fseq, lowers[i]); unsigned fsv_upper = um.sign_variations_at(fseq, uppers[i]); - SASSERT(um.eval_sign_at(q.size(), q.c_ptr(), lowers[i]) == 0 || - um.eval_sign_at(q.size(), q.c_ptr(), uppers[i]) == 0 || + VERIFY(um.eval_sign_at(q.size(), q.c_ptr(), lowers[i]) == 0 || + um.eval_sign_at(q.size(), q.c_ptr(), uppers[i]) == 0 || // fsv_lower - fsv_upper is an upper bound for the number of roots in the interval // fsv_upper - fsv_upper - num_roots is even // Recall that num_roots == 1 in the interval. - (fsv_lower - fsv_upper >= 1 && (fsv_lower - fsv_upper - 1) % 2 == 0)); - + (fsv_lower - fsv_upper >= 1 && (fsv_lower - fsv_upper - 1) % 2 == 0)); + // Double checking using Descartes bounds for the interval // Must use square free component. unsigned dab = um.descartes_bound_a_b(q_sqf.size(), q_sqf.c_ptr(), bqm, lowers[i], uppers[i]); TRACE("upolynomial", tout << "Descartes bound: " << dab << "\n";); - SASSERT(dab == 1); + VERIFY(dab == 1); } } std::cout << "\n"; @@ -499,7 +499,7 @@ static void tst_refinable(polynomial_ref const & p, mpbq_manager & bqm, mpbq & a std::cout << "new (" << bqm.to_string(a) << ", " << bqm.to_string(b) << ")\n"; int sign_a = um.eval_sign_at(_p.size(), _p.c_ptr(), a); int sign_b = um.eval_sign_at(_p.size(), _p.c_ptr(), b); - SASSERT(sign_a != 0 && sign_b != 0 && sign_a == -sign_b); + VERIFY(sign_a != 0 && sign_b != 0 && sign_a == -sign_b); } else { std::cout << "new root: " << bqm.to_string(a) << "\n"; From cba9a160d3f4662fdebb75c6d5f4112afc11a216 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 4 Jul 2017 19:42:22 -0700 Subject: [PATCH 111/159] deal with warning messages Signed-off-by: Nikolaj Bjorner --- src/test/cnf_backbones.cpp | 2 ++ src/test/dl_context.cpp | 3 ++- src/test/polynorm.cpp | 3 ++- src/test/sat_user_scope.cpp | 5 ----- src/test/upolynomial.cpp | 4 ++-- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/test/cnf_backbones.cpp b/src/test/cnf_backbones.cpp index 14fc594b6..3fdf96f87 100644 --- a/src/test/cnf_backbones.cpp +++ b/src/test/cnf_backbones.cpp @@ -38,6 +38,7 @@ static void STD_CALL on_ctrl_c(int) { raise(SIGINT); } +#if 0 static void display_model(sat::solver const & s) { sat::model const & m = s.get_model(); for (unsigned i = 1; i < m.size(); i++) { @@ -49,6 +50,7 @@ static void display_model(sat::solver const & s) { } std::cout << "\n"; } +#endif static void display_status(lbool r) { switch (r) { diff --git a/src/test/dl_context.cpp b/src/test/dl_context.cpp index 99a0480a6..8a62dcb7d 100644 --- a/src/test/dl_context.cpp +++ b/src/test/dl_context.cpp @@ -15,11 +15,12 @@ using namespace datalog; void tst_dl_context() { - symbol relations[] = { symbol("tr_skip"), symbol("tr_sparse"), symbol("tr_hashtable"), symbol("smt_relation2") }; return; #if 0 + symbol relations[] = { symbol("tr_skip"), symbol("tr_sparse"), symbol("tr_hashtable"), symbol("smt_relation2") }; + const unsigned rel_cnt = sizeof(relations)/sizeof(symbol); const char * test_file = "c:\\tvm\\src\\benchmarks\\datalog\\t0.datalog"; diff --git a/src/test/polynorm.cpp b/src/test/polynorm.cpp index 0bc9dfe3c..987d8e13b 100644 --- a/src/test/polynorm.cpp +++ b/src/test/polynorm.cpp @@ -89,6 +89,7 @@ private: expr_ref_vector& coefficients = poly.coefficients(); expr_ref& coefficient = poly.coefficient(); (void) coefficient; + (void) coefficients; m_rw(term); @@ -171,7 +172,7 @@ static expr_ref mk_mul(arith_util& arith, unsigned num_args, expr* const* args) static void nf(expr_ref& term) { ast_manager& m = term.get_manager(); - expr *e1, *e2; + expr *e1 = 0, *e2 = 0; th_rewriter rw(m); arith_util arith(m); diff --git a/src/test/sat_user_scope.cpp b/src/test/sat_user_scope.cpp index 54de5976a..a271ce6bb 100644 --- a/src/test/sat_user_scope.cpp +++ b/src/test/sat_user_scope.cpp @@ -34,11 +34,6 @@ static void add_clause(sat::solver& s, random_gen& r, trail_t& t) { s.mk_clause(cls.size(), cls.c_ptr()); } -static void display_state(std::ostream& out, sat::solver& s, trail_t& t) { - (void)t; - s.display(out); -} - static void pop_user_scope(sat::solver& s, trail_t& t) { std::cout << "pop\n"; s.user_pop(1); diff --git a/src/test/upolynomial.cpp b/src/test/upolynomial.cpp index 3d9815873..43aefed99 100644 --- a/src/test/upolynomial.cpp +++ b/src/test/upolynomial.cpp @@ -164,7 +164,7 @@ static void check_roots(mpbq_vector const & roots, mpbq_vector const & lowers, m for (unsigned j = 0; j < roots.size(); j++) { if (to_rational(roots[j]) == r) { SASSERT(!visited[j]); - SASSERT(!found); + VERIFY(!found); found = true; visited[j] = true; } @@ -172,7 +172,7 @@ static void check_roots(mpbq_vector const & roots, mpbq_vector const & lowers, m for (unsigned j = 0; j < lowers.size(); j++) { unsigned j_prime = j + roots.size(); if (to_rational(lowers[j]) < r && r < to_rational(uppers[j])) { - SASSERT(!found); + VERIFY(!found); SASSERT(!visited[j_prime]); found = true; visited[j_prime] = true; From 41803ec1cf280ae9634389d17f99bf69a2b597ef Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 4 Jul 2017 19:55:38 -0700 Subject: [PATCH 112/159] fix trace/debug build for unreferenced variables Signed-off-by: Nikolaj Bjorner --- src/smt/theory_str.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/smt/theory_str.cpp b/src/smt/theory_str.cpp index d8d130212..5d46b5349 100644 --- a/src/smt/theory_str.cpp +++ b/src/smt/theory_str.cpp @@ -5619,7 +5619,7 @@ namespace smt { } void theory_str::print_grounded_concat(expr * node, std::map, std::set > > & groundedMap) { - TRACE("str", tout << mk_pp(node, m) << std::endl;); + TRACE("str", tout << mk_pp(node, get_manager()) << std::endl;); if (groundedMap.find(node) != groundedMap.end()) { std::map, std::set >::iterator itor = groundedMap[node].begin(); for (; itor != groundedMap[node].end(); ++itor) { @@ -7515,7 +7515,7 @@ namespace smt { while (varItor != cut_var_map.end()) { std::stack & val = cut_var_map[varItor->m_key]; while ((val.size() > 0) && (val.top()->level != 0) && (val.top()->level >= sLevel)) { - TRACE("str", tout << "remove cut info for " << mk_pp(e, get_manager()) << std::endl; print_cut_var(e, tout);); + // TRACE("str", tout << "remove cut info for " << mk_pp(e, get_manager()) << std::endl; print_cut_var(e, tout);); // T_cut * aCut = val.top(); val.pop(); // dealloc(aCut); @@ -8828,7 +8828,7 @@ namespace smt { // break; } else { // debug - TRACE("str", tout << "variable " << mk_pp(itor->first, m) << " = " << mk_pp(eqcString, m) << std::endl;); + // TRACE("str", tout << "variable " << mk_pp(itor->first, m) << " = " << mk_pp(eqcString, m) << std::endl;); } } } @@ -9315,8 +9315,8 @@ namespace smt { << mk_ismt2_pp(makeupAssert, m) << std::endl;); assert_axiom(makeupAssert); } else { - TRACE("str", tout << "value tester " << mk_ismt2_pp(aTester, m) - << " == " << mk_ismt2_pp(aTester_eqc_value, m) << std::endl;); + // TRACE("str", tout << "value tester " << mk_ismt2_pp(aTester, m) + // << " == " << mk_ismt2_pp(aTester_eqc_value, m) << std::endl;); } } @@ -10334,7 +10334,7 @@ namespace smt { } if (duplicated && dupVar != NULL) { TRACE("str", tout << "Duplicated free variable found:" << mk_pp(freeVar, get_manager()) - << " = " << mk_ismt2_pp(dupVar, m) << " (SKIP)" << std::endl;); + << " = " << mk_ismt2_pp(dupVar, get_manager()) << " (SKIP)" << std::endl;); continue; } else { eqcRepSet.insert(freeVar); From b14364a11759d563edd104922b7d38ccb22f20aa Mon Sep 17 00:00:00 2001 From: Murphy Berzish Date: Wed, 5 Jul 2017 11:06:40 -0400 Subject: [PATCH 113/159] fix theory_str warnings: rename get_value() to get_arith_value() --- src/smt/theory_str.cpp | 15 ++++++++------- src/smt/theory_str.h | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/smt/theory_str.cpp b/src/smt/theory_str.cpp index 5d46b5349..2e928af37 100644 --- a/src/smt/theory_str.cpp +++ b/src/smt/theory_str.cpp @@ -1984,7 +1984,8 @@ namespace smt { return NULL; } - static inline std::string rational_to_string_if_exists(const rational & x, bool x_exists) { + // trace code helper + inline std::string rational_to_string_if_exists(const rational & x, bool x_exists) { if (x_exists) { return x.to_string(); } else { @@ -4651,7 +4652,7 @@ namespace smt { } } - bool theory_str::get_value(expr* e, rational& val) const { + bool theory_str::get_arith_value(expr* e, rational& val) const { if (opt_DisableIntegerTheoryIntegration) { TRACE("str", tout << "WARNING: integer theory integration disabled" << std::endl;); return false; @@ -4780,7 +4781,7 @@ namespace smt { } }); - if (ctx.e_internalized(len) && get_value(len, val1)) { + if (ctx.e_internalized(len) && get_arith_value(len, val1)) { val += val1; TRACE("str", tout << "integer theory: subexpression " << mk_ismt2_pp(len, m) << " has length " << val1 << std::endl;); } @@ -8439,7 +8440,7 @@ namespace smt { // check integer theory rational Ival; - bool Ival_exists = get_value(a, Ival); + bool Ival_exists = get_arith_value(a, Ival); if (Ival_exists) { TRACE("str", tout << "integer theory assigns " << mk_pp(a, m) << " = " << Ival.to_string() << std::endl;); // if that value is not -1, we can assert (str.to-int S) = Ival --> S = "Ival" @@ -8610,7 +8611,7 @@ namespace smt { rational lenValue; expr_ref concatlenExpr (mk_strlen(concat), m) ; bool allLeafResolved = true; - if (! get_value(concatlenExpr, lenValue)) { + if (! get_arith_value(concatlenExpr, lenValue)) { // the length fo concat is unresolved yet if (get_len_value(concat, lenValue)) { // but all leaf nodes have length information @@ -8647,7 +8648,7 @@ namespace smt { expr * var = *it; rational lenValue; expr_ref varlen (mk_strlen(var), m) ; - if (! get_value(varlen, lenValue)) { + if (! get_arith_value(varlen, lenValue)) { if (propagate_length_within_eqc(var)) { axiomAdded = true; } @@ -9479,7 +9480,7 @@ namespace smt { bool unrLenValue_exists = get_len_value(unrFunc, unrLenValue); tout << "unroll length: " << (unrLenValue_exists ? unrLenValue.to_string() : "?") << std::endl; rational cntInUnrValue; - bool cntHasValue = get_value(cntInUnr, cntInUnrValue); + bool cntHasValue = get_arith_value(cntInUnr, cntInUnrValue); tout << "unroll count: " << (cntHasValue ? cntInUnrValue.to_string() : "?") << " low = " << (low_exists ? low.to_string() : "?") diff --git a/src/smt/theory_str.h b/src/smt/theory_str.h index 0bbc44ab8..7f39efa70 100644 --- a/src/smt/theory_str.h +++ b/src/smt/theory_str.h @@ -219,7 +219,7 @@ protected: /* * If DisableIntegerTheoryIntegration is set to true, * ALL calls to the integer theory integration methods - * (get_value, get_len_value, lower_bound, upper_bound) + * (get_arith_value, get_len_value, lower_bound, upper_bound) * will ignore what the arithmetic solver believes about length terms, * and will return no information. * @@ -464,7 +464,7 @@ protected: bool in_same_eqc(expr * n1, expr * n2); expr * collect_eq_nodes(expr * n, expr_ref_vector & eqcSet); - bool get_value(expr* e, rational& val) const; + bool get_arith_value(expr* e, rational& val) const; bool get_len_value(expr* e, rational& val); bool lower_bound(expr* _e, rational& lo); bool upper_bound(expr* _e, rational& hi); From 465ed7d068938d5b87cd8ede517f0e93b4ffe67f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 5 Jul 2017 10:21:57 -0700 Subject: [PATCH 114/159] adding doc #1132 Signed-off-by: Nikolaj Bjorner --- src/api/z3_api.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 63f1d15ff..386fdd8a2 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -396,6 +396,33 @@ typedef enum The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) + - Z3_OP_BSMUL_NO_OVFL: a predicate to check that bit-wise signed multiplication does not overflow. + Signed multiplication overflows if the operands have the same sign and the result of multiplication + does not fit within the available bits. \sa Z3_mk_bvmul_no_overflow. + + - Z3_OP_BUMUL_NO_OVFL: check that bit-wise unsigned multiplication does not overflow. + Unsigned multiplication overflows if the result does not fit within the available bits. + \sa Z3_mk_bvmul_no_overflow. + + - Z3_OP_BSMUL_NO_UDFL: check that bit-wise signed multiplication does not underflow. + Signed multiplication underflows if the operands have opposite signs and the result of multiplication + does not fit within the avaialble bits. Z3_mk_bvmul_no_underflow. + + - Z3_OP_BSDIV_I: Binary signed division. + It has the same semantics as Z3_OP_BSDIV, but created in a context where the second operand can be assumed to be non-zero. + + - Z3_OP_BUDIV_I: Binary unsigned division. + It has the same semantics as Z3_OP_BUDIV, but created in a context where the second operand can be assumed to be non-zero. + + - Z3_OP_BSREM_I: Binary signed remainder. + It has the same semantics as Z3_OP_BSREM, but created in a context where the second operand can be assumed to be non-zero. + + - Z3_OP_BUREM_I: Binary unsigned remainder. + It has the same semantics as Z3_OP_BUREM, but created in a context where the second operand can be assumed to be non-zero. + + - Z3_OP_BSMOD_I: Binary signed modulus. + It has the same semantics as Z3_OP_BSMOND, but created in a context where the second operand can be assumed to be non-zero. + - Z3_OP_PR_UNDEF: Undef/Null proof object. - Z3_OP_PR_TRUE: Proof for the expression 'true'. From 4c23527974aa50d37c49725f1581906400612ecf Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 6 Jul 2017 08:53:08 -0700 Subject: [PATCH 115/159] Dev (#63) * introduce int_solver.h Signed-off-by: Lev Nachmanson * add int_solver class Signed-off-by: Lev Nachmanson * track which var is an integer Signed-off-by: Lev Nachmanson * add queries for integrality of vars Signed-off-by: Lev Nachmanson * resurrect lp_tst in its own director lp Signed-off-by: Lev Nachmanson * add file Signed-off-by: Lev Nachmanson * add_constraint has got a body Signed-off-by: Lev Nachmanson * fix add_constraint and substitute_terms_in_linear_expression Signed-off-by: Lev Nachmanson * after merge with Z3Prover Signed-off-by: Lev Nachmanson * adding stub check_int_feasibility() Signed-off-by: Lev Nachmanson * Dev (#50) * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * small fix in lar_solver.cpp Signed-off-by: Lev Nachmanson * adding some content to the new check_int_feasibility() Signed-off-by: Lev Nachmanson * Dev (#51) * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * adding more nlsat Signed-off-by: Nikolaj Bjorner * nlsat integration Signed-off-by: Nikolaj Bjorner * adding constraints Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * add missing initialization Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * test Signed-off-by: Lev Nachmanson * Dev (#53) * change in a comment Signed-off-by: Lev Nachmanson * Disabled debug output * removing FOCI2 interface from interp * remove foci reference from cmakelist.txt Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * adding more nlsat Signed-off-by: Nikolaj Bjorner * nlsat integration Signed-off-by: Nikolaj Bjorner * adding constraints Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * add missing initialization Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * adding nra Signed-off-by: Nikolaj Bjorner * debugging nra Signed-off-by: Nikolaj Bjorner * updates to nra_solver integration to call it directly from theory_lra instead of over lar_solver Signed-off-by: Nikolaj Bjorner * n/a Signed-off-by: Nikolaj Bjorner * integrate nlsat Signed-off-by: Nikolaj Bjorner * tidy Signed-off-by: Nikolaj Bjorner * preserve is_int flag Signed-off-by: Lev Nachmanson * remove a debug printout Signed-off-by: Lev Nachmanson * Dev (#54) * change in a comment Signed-off-by: Lev Nachmanson * Disabled debug output * removing FOCI2 interface from interp * remove foci reference from cmakelist.txt Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * adding more nlsat Signed-off-by: Nikolaj Bjorner * nlsat integration Signed-off-by: Nikolaj Bjorner * adding constraints Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * add missing initialization Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * adding nra Signed-off-by: Nikolaj Bjorner * debugging nra Signed-off-by: Nikolaj Bjorner * updates to nra_solver integration to call it directly from theory_lra instead of over lar_solver Signed-off-by: Nikolaj Bjorner * n/a Signed-off-by: Nikolaj Bjorner * integrate nlsat Signed-off-by: Nikolaj Bjorner * tidy Signed-off-by: Nikolaj Bjorner * use integer test from lra solver, updated it to work on term variables Signed-off-by: Nikolaj Bjorner * fix equality check in assume-eq Signed-off-by: Nikolaj Bjorner * fix model_is_int_feasible Signed-off-by: Lev Nachmanson * untested gcd_test() Signed-off-by: Lev Nachmanson * call fill_explanation_from_fixed_columns() Signed-off-by: Lev Nachmanson * add the call to pivot_fixed_vars_from_basis() to int_solver.cpp::check() Signed-off-by: Lev Nachmanson * port more of theory_arith_int.h Signed-off-by: Lev Nachmanson * use statistics of lar_solver by theory_lra.cpp Signed-off-by: Lev Nachmanson * port more code to int_solver.cpp Signed-off-by: Lev Nachmanson * add an assert Signed-off-by: Lev Nachmanson * more int porting Signed-off-by: Lev Nachmanson * fix a bug in pivot_fixed_vars_from_basis Signed-off-by: Lev Nachmanson * small change Signed-off-by: Lev Nachmanson * implement find_inf_int_base_column() Signed-off-by: Lev Nachmanson * catch unregistered vars in add_var_bound Signed-off-by: Lev Nachmanson * add a file Signed-off-by: Lev Nachmanson * compile for vs2012 Signed-off-by: Lev Nachmanson * fix asserts in add_var_bound Signed-off-by: Lev Nachmanson * fix the lp_solver init when workig on an mps file Signed-off-by: Lev Nachmanson * towards int_solver::check() Signed-off-by: Lev Nachmanson * change in int_solver::check() signature Signed-off-by: Lev Nachmanson * add handlers for lia moves Signed-off-by: Nikolaj Bjorner * spacing Signed-off-by: Nikolaj Bjorner * return branch from int_solver::check() Signed-off-by: Lev Nachmanson * add a stub for mk_gomory_cut Signed-off-by: Lev Nachmanson * Dev (#59) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner * spacing Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * Dev (#60) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner * spacing Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * Dev (#61) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner * spacing Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * more TRACE(arith_int) Signed-off-by: Lev Nachmanson * fix the build Signed-off-by: Lev Nachmanson * loops Signed-off-by: Nikolaj Bjorner * Dev (#62) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner * spacing Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * build fix Signed-off-by: Lev Nachmanson --- src/smt/theory_arith_int.h | 6 +- src/smt/theory_lra.cpp | 112 +++++++++++++------ src/util/lp/int_solver.cpp | 224 +++++++++++++++++++++++++++++++++---- src/util/lp/int_solver.h | 2 + src/util/lp/lar_term.h | 4 + 5 files changed, 291 insertions(+), 57 deletions(-) diff --git a/src/smt/theory_arith_int.h b/src/smt/theory_arith_int.h index e6e9e863c..ca3a485c6 100644 --- a/src/smt/theory_arith_int.h +++ b/src/smt/theory_arith_int.h @@ -201,10 +201,12 @@ namespace smt { SASSERT(is_int(v)); SASSERT(!get_value(v).is_int()); m_stats.m_branches++; - TRACE("arith_int", tout << "branching v" << v << " = " << get_value(v) << "\n"; - display_var(tout, v);); numeral k = ceil(get_value(v)); rational _k = k.to_rational(); + TRACE("arith_int", tout << "branching v" << v << " = " << get_value(v) << "\n"; + display_var(tout, v); + tout << "k = " << k << ", _k = "<< _k << std::endl; + ); expr_ref bound(get_manager()); expr* e = get_enode(v)->get_owner(); bound = m_util.mk_ge(e, m_util.mk_numeral(_k, m_util.is_int(e))); diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index c35dbb94e..43d3820f3 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -54,13 +54,15 @@ namespace lp { class bound { smt::bool_var m_bv; smt::theory_var m_var; + bool m_is_int; rational m_value; bound_kind m_bound_kind; public: - bound(smt::bool_var bv, smt::theory_var v, rational const & val, bound_kind k): + bound(smt::bool_var bv, smt::theory_var v, bool is_int, rational const & val, bound_kind k): m_bv(bv), m_var(v), + m_is_int(is_int), m_value(val), m_bound_kind(k) { } @@ -68,11 +70,18 @@ namespace lp { smt::theory_var get_var() const { return m_var; } smt::bool_var get_bv() const { return m_bv; } bound_kind get_bound_kind() const { return m_bound_kind; } + bool is_int() const { return m_is_int; } rational const& get_value() const { return m_value; } inf_rational get_value(bool is_true) const { if (is_true) return inf_rational(m_value); // v >= value or v <= value - if (m_bound_kind == lower_t) return inf_rational(m_value, false); // v <= value - epsilon - return inf_rational(m_value, true); // v >= value + epsilon + if (m_is_int) { + if (m_bound_kind == lower_t) return inf_rational(m_value - rational::one()); // v <= value - 1 + return inf_rational(m_value + rational::one()); // v >= value + 1 + } + else { + if (m_bound_kind == lower_t) return inf_rational(m_value, false); // v <= value - epsilon + return inf_rational(m_value, true); // v >= value + epsilon + } } virtual std::ostream& display(std::ostream& out) const { return out << "v" << get_var() << " " << get_bound_kind() << " " << m_value; @@ -305,7 +314,6 @@ namespace smt { } } - void found_not_handled(expr* n) { m_not_handled = n; if (is_app(n) && is_underspecified(to_app(n))) { @@ -756,7 +764,7 @@ namespace smt { found_not_handled(atom); return true; } - lp::bound* b = alloc(lp::bound, bv, v, r, k); + lp::bound* b = alloc(lp::bound, bv, v, is_int(v), r, k); m_bounds[v].push_back(b); updt_unassigned_bounds(v, +1); m_bounds_trail.push_back(v); @@ -1211,33 +1219,49 @@ namespace smt { return FC_GIVEUP; } - // create a bound atom representing term >= k - lp::bound* mk_bound(lean::lar_term const& term, rational const& k) { - NOT_IMPLEMENTED_YET(); - lp::bound_kind bkind = lp::bound_kind::lower_t; - bool_var bv = null_bool_var; - theory_var v = null_theory_var; - lp::bound* result = alloc(lp::bound, bv, v, k, bkind); - return result; + // create a bound atom representing term <= k + app_ref mk_bound(lean::lar_term const& term, rational const& k) { + SASSERT(k.is_int()); + app_ref t = mk_term(term, true); + app_ref atom(a.mk_le(t, a.mk_numeral(k, true)), m); + TRACE("arith", tout << atom << "\n"; + m_solver->print_term(term, tout << "bound atom: "); tout << " <= " << k << "\n"; + display(tout); + ); + ctx().internalize(atom, true); + ctx().mark_as_relevant(atom.get()); + return atom; } lbool check_lia() { - std::cout << "called check_lia()\n"; + if (m.canceled()) return l_undef; lean::lar_term term; lean::mpq k; lean::explanation ex; // TBD, this should be streamlined accross different explanations switch(m_lia->check(term, k, ex)) { case lean::lia_move::ok: return l_true; - case lean::lia_move::branch: + case lean::lia_move::branch: { + (void)mk_bound(term, k); // branch on term <= k - NOT_IMPLEMENTED_YET(); + // at this point we have a new unassigned atom that the + // SAT core assigns a value to return l_false; - case lean::lia_move::cut: + } + case lean::lia_move::cut: { // m_explanation implies term <= k - m_explanation = ex.m_explanation; - NOT_IMPLEMENTED_YET(); + app_ref b = mk_bound(term, k); + m_eqs.reset(); + m_core.reset(); + m_params.reset(); + for (auto const& ev : ex.m_explanation) { + if (!ev.first.is_zero()) { + set_evidence(ev.second); + } + } + assign(literal(ctx().get_bool_var(b), false)); return l_false; + } case lean::lia_move::conflict: // ex contains unsat core m_explanation = ex.m_explanation; @@ -2030,12 +2054,13 @@ namespace smt { st.coeffs().push_back(rational::one()); init_left_side(st); lean::lconstraint_kind k = lean::EQ; + bool is_int = b.is_int(); switch (b.get_bound_kind()) { case lp::lower_t: - k = is_true ? lean::GE : lean::LT; + k = is_true ? lean::GE : (is_int ? lean::LE : lean::LT); break; case lp::upper_t: - k = is_true ? lean::LE : lean::GT; + k = is_true ? lean::LE : (is_int ? lean::GE : lean::GT); break; } if (k == lean::LT || k == lean::LE) { @@ -2045,7 +2070,15 @@ namespace smt { ++m_stats.m_assert_upper; } auto vi = get_var_index(b.get_var()); - auto ci = m_solver->add_var_bound(vi, k, b.get_value()); + rational bound = b.get_value(); + lean::constraint_index ci; + if (is_int && !is_true) { + rational bound = b.get_value(false).get_rational(); + ci = m_solver->add_var_bound(vi, k, bound); + } + else { + ci = m_solver->add_var_bound(vi, k, b.get_value()); + } TRACE("arith", tout << "v" << b.get_var() << "\n";); add_ineq_constraint(ci, literal(bv, !is_true)); @@ -2499,19 +2532,32 @@ namespace smt { return internalize_def(term); } + app_ref mk_term(lean::lar_term const& term, bool is_int) { + expr_ref_vector args(m); + for (auto & ti : term.m_coeffs) { + theory_var w = m_var_index2theory_var[ti.first]; + expr* o = get_enode(w)->get_owner(); + if (ti.second.is_one()) { + args.push_back(o); + } + else { + args.push_back(a.mk_mul(a.mk_numeral(ti.second, is_int), o)); + } + } + if (!term.m_v.is_zero()) { + args.push_back(a.mk_numeral(term.m_v, is_int)); + } + if (args.size() == 1) { + return app_ref(to_app(args[0].get()), m); + } + return app_ref(a.mk_add(args.size(), args.c_ptr()), m); + } + app_ref mk_obj(theory_var v) { lean::var_index vi = m_theory_var2var_index[v]; bool is_int = a.is_int(get_enode(v)->get_owner()); - if (m_solver->is_term(vi)) { - expr_ref_vector args(m); - const lean::lar_term& term = m_solver->get_term(vi); - for (auto & ti : term.m_coeffs) { - theory_var w = m_var_index2theory_var[ti.first]; - expr* o = get_enode(w)->get_owner(); - args.push_back(a.mk_mul(a.mk_numeral(ti.second, is_int), o)); - } - args.push_back(a.mk_numeral(term.m_v, is_int)); - return app_ref(a.mk_add(args.size(), args.c_ptr()), m); + if (m_solver->is_term(vi)) { + return mk_term(m_solver->get_term(vi), is_int); } else { theory_var w = m_var_index2theory_var[vi]; @@ -2537,7 +2583,7 @@ namespace smt { // ctx().set_enode_flag(bv, true); lp::bound_kind bkind = lp::bound_kind::lower_t; if (is_strict) bkind = lp::bound_kind::upper_t; - lp::bound* a = alloc(lp::bound, bv, v, r, bkind); + lp::bound* a = alloc(lp::bound, bv, v, is_int, r, bkind); mk_bound_axioms(*a); updt_unassigned_bounds(v, +1); m_bounds[v].push_back(a); diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index e617a1e29..1a6d6ddae 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -101,6 +101,186 @@ int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { } +bool int_solver::mk_gomory_cut(unsigned row_index, explanation & ex) { + lean_assert(false); + return true; + /* + const auto & row = m_lar_solver->A_r().m_rows[row_index]; + // The following assertion is wrong. It may be violated in mixed-integer problems. + // SASSERT(!all_coeff_int(r)); + theory_var x_i = r.get_base_var(); + + SASSERT(is_int(x_i)); + // The following assertion is wrong. It may be violated in mixed-real-interger problems. + // The check is_gomory_cut_target will discard rows where any variable contains infinitesimals. + // SASSERT(m_value[x_i].is_rational()); // infinitesimals are not used for integer variables + SASSERT(!m_value[x_i].is_int()); // the base variable is not assigned to an integer value. + + if (constrain_free_vars(r) || !is_gomory_cut_target(r)) { + TRACE("gomory_cut", tout << "failed to apply gomory cut:\n"; + tout << "constrain_free_vars(r): " << constrain_free_vars(r) << "\n";); + return false; + } + + TRACE("gomory_cut", tout << "applying cut at:\n"; display_row_info(tout, r);); + + antecedents ante(*this); + + m_stats.m_gomory_cuts++; + + // gomory will be pol >= k + numeral k(1); + buffer pol; + + numeral f_0 = Ext::fractional_part(m_value[x_i]); + numeral one_minus_f_0 = numeral(1) - f_0; + SASSERT(!f_0.is_zero()); + SASSERT(!one_minus_f_0.is_zero()); + + numeral lcm_den(1); + unsigned num_ints = 0; + + typename vector::const_iterator it = r.begin_entries(); + typename vector::const_iterator end = r.end_entries(); + for (; it != end; ++it) { + if (!it->is_dead() && it->m_var != x_i) { + theory_var x_j = it->m_var; + numeral a_ij = it->m_coeff; + a_ij.neg(); // make the used format compatible with the format used in: Integrating Simplex with DPLL(T) + if (is_real(x_j)) { + numeral new_a_ij; + if (at_lower(x_j)) { + if (a_ij.is_pos()) { + new_a_ij = a_ij / one_minus_f_0; + } + else { + new_a_ij = a_ij / f_0; + new_a_ij.neg(); + } + k.addmul(new_a_ij, lower_bound(x_j).get_rational()); + lower(x_j)->push_justification(ante, new_a_ij, coeffs_enabled()); + } + else { + SASSERT(at_upper(x_j)); + if (a_ij.is_pos()) { + new_a_ij = a_ij / f_0; + new_a_ij.neg(); // the upper terms are inverted. + } + else { + new_a_ij = a_ij / one_minus_f_0; + } + k.addmul(new_a_ij, upper_bound(x_j).get_rational()); + upper(x_j)->push_justification(ante, new_a_ij, coeffs_enabled()); + } + TRACE("gomory_cut_detail", tout << a_ij << "*v" << x_j << " k: " << k << "\n";); + pol.push_back(row_entry(new_a_ij, x_j)); + } + else { + ++num_ints; + SASSERT(is_int(x_j)); + numeral f_j = Ext::fractional_part(a_ij); + TRACE("gomory_cut_detail", + tout << a_ij << "*v" << x_j << "\n"; + tout << "fractional_part: " << Ext::fractional_part(a_ij) << "\n"; + tout << "f_j: " << f_j << "\n"; + tout << "f_0: " << f_0 << "\n"; + tout << "one_minus_f_0: " << one_minus_f_0 << "\n";); + if (!f_j.is_zero()) { + numeral new_a_ij; + if (at_lower(x_j)) { + if (f_j <= one_minus_f_0) { + new_a_ij = f_j / one_minus_f_0; + } + else { + new_a_ij = (numeral(1) - f_j) / f_0; + } + k.addmul(new_a_ij, lower_bound(x_j).get_rational()); + lower(x_j)->push_justification(ante, new_a_ij, coeffs_enabled()); + } + else { + SASSERT(at_upper(x_j)); + if (f_j <= f_0) { + new_a_ij = f_j / f_0; + } + else { + new_a_ij = (numeral(1) - f_j) / one_minus_f_0; + } + new_a_ij.neg(); // the upper terms are inverted + k.addmul(new_a_ij, upper_bound(x_j).get_rational()); + upper(x_j)->push_justification(ante, new_a_ij, coeffs_enabled()); + } + TRACE("gomory_cut_detail", tout << "new_a_ij: " << new_a_ij << " k: " << k << "\n";); + pol.push_back(row_entry(new_a_ij, x_j)); + lcm_den = lcm(lcm_den, denominator(new_a_ij)); + } + } + } + } + + CTRACE("empty_pol", pol.empty(), display_row_info(tout, r);); + + expr_ref bound(get_manager()); + if (pol.empty()) { + SASSERT(k.is_pos()); + // conflict 0 >= k where k is positive + set_conflict(ante, ante, "gomory-cut"); + return true; + } + else if (pol.size() == 1) { + theory_var v = pol[0].m_var; + k /= pol[0].m_coeff; + bool is_lower = pol[0].m_coeff.is_pos(); + if (is_int(v) && !k.is_int()) { + k = is_lower?ceil(k):floor(k); + } + rational _k = k.to_rational(); + if (is_lower) + bound = m_util.mk_ge(get_enode(v)->get_owner(), m_util.mk_numeral(_k, is_int(v))); + else + bound = m_util.mk_le(get_enode(v)->get_owner(), m_util.mk_numeral(_k, is_int(v))); + } + else { + if (num_ints > 0) { + lcm_den = lcm(lcm_den, denominator(k)); + TRACE("gomory_cut_detail", tout << "k: " << k << " lcm_den: " << lcm_den << "\n"; + for (unsigned i = 0; i < pol.size(); i++) { + tout << pol[i].m_coeff << " " << pol[i].m_var << "\n"; + } + tout << "k: " << k << "\n";); + SASSERT(lcm_den.is_pos()); + if (!lcm_den.is_one()) { + // normalize coefficients of integer parameters to be integers. + unsigned n = pol.size(); + for (unsigned i = 0; i < n; i++) { + pol[i].m_coeff *= lcm_den; + SASSERT(!is_int(pol[i].m_var) || pol[i].m_coeff.is_int()); + } + k *= lcm_den; + } + TRACE("gomory_cut_detail", tout << "after *lcm\n"; + for (unsigned i = 0; i < pol.size(); i++) { + tout << pol[i].m_coeff << " * v" << pol[i].m_var << "\n"; + } + tout << "k: " << k << "\n";); + } + mk_polynomial_ge(pol.size(), pol.c_ptr(), k.to_rational(), bound); + } + TRACE("gomory_cut", tout << "new cut:\n" << bound << "\n"; ante.display(tout);); + literal l = null_literal; + context & ctx = get_context(); + ctx.internalize(bound, true); + l = ctx.get_literal(bound); + ctx.mark_as_relevant(l); + dump_lemmas(l, ante); + ctx.assign(l, ctx.mk_justification( + gomory_cut_justification( + get_id(), ctx.get_region(), + ante.lits().size(), ante.lits().c_ptr(), + ante.eqs().size(), ante.eqs().c_ptr(), ante, l))); + return true; + */ + +} lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { lean_assert(is_feasible()); init_inf_int_set(); @@ -129,32 +309,35 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { if ((++m_branch_cut_counter) % settings().m_int_branch_cut_threshold == 0) { move_non_base_vars_to_bounds(); - /* - if (!make_feasible()) { - TRACE("arith_int", tout << "failed to move variables to bounds.\n";); - failed(); - return FC_CONTINUE; + lp_status st = m_lar_solver->find_feasible_solution(); + if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) { + return lia_move::give_up; } - int int_var = find_inf_int_base_var(); - if (int_var != null_int) { - TRACE("arith_int", tout << "v" << int_var << " does not have an integer assignment: " << get_value(int_var) << "\n";); - SASSERT(is_base(int_var)); - row const & r = m_rows[get_var_row(int_var)]; - if (!mk_gomory_cut(r)) { + int j = find_inf_int_base_column(); + if (j != -1) { + TRACE("arith_int", tout << "j = " << j << " does not have an integer assignment: " << get_value(j) << "\n";); + unsigned row_index = m_lar_solver->m_mpq_lar_core_solver.m_r_heading[j]; + if (!mk_gomory_cut(row_index, ex)) { + return lia_move::give_up; // silent failure } - return FC_CONTINUE; - }*/ + return lia_move::cut; + } } else { int j = find_inf_int_base_column(); - /* if (j != -1) { - TRACE("arith_int", tout << "v" << j << " does not have an integer assignment: " << get_value(j) << "\n";); - // apply branching - branch_infeasible_int_var(int_var); - return false; - }*/ + TRACE("arith_int", tout << "j" << j << " does not have an integer assignment: " << get_value(j) << "\n";); + + lean_assert(t.is_empty()); + t.add_to_map(j, mpq(1)); + k = floor(get_value(j)); + TRACE("arith_int", tout << "branching v" << j << " = " << get_value(j) << "\n"; + display_column(tout, j); + tout << "k = " << k << std::endl; + ); + return lia_move::branch; + } } // return true; return lia_move::give_up; @@ -259,7 +442,6 @@ mpq get_denominators_lcm(iterator_on_row &it) { bool int_solver::gcd_test_for_row(static_matrix> & A, unsigned i, explanation & ex) { iterator_on_row it(A.m_rows[i]); - std::cout << "gcd_test_for_row(" << i << ")\n"; mpq lcm_den = get_denominators_lcm(it); mpq consts(0); mpq gcds(0); @@ -350,8 +532,6 @@ bool int_solver::ext_gcd_test(iterator_on_row & it, mpq const & least_coeff, mpq const & lcm_den, mpq const & consts, explanation& ex) { - - std::cout << "calling ext_gcd_test" << std::endl; mpq gcds(0); mpq l(consts); mpq u(consts); diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index 981127bc8..edfba5e5b 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -96,5 +96,7 @@ private: int find_inf_int_boxed_base_column_with_smallest_range(); lp_settings& settings(); void move_non_base_vars_to_bounds(); + void branch_infeasible_int_var(unsigned); + bool mk_gomory_cut(unsigned row_index, explanation & ex); }; } diff --git a/src/util/lp/lar_term.h b/src/util/lp/lar_term.h index 0e715ad0b..dfdedb571 100644 --- a/src/util/lp/lar_term.h +++ b/src/util/lp/lar_term.h @@ -21,6 +21,10 @@ struct lar_term { } } + bool is_empty() const { + return m_coeffs.size() == 0 && is_zero(m_v); + } + unsigned size() const { return static_cast(m_coeffs.size()); } const std::unordered_map & coeffs() const { From b21741cccdff6d70de0d69e70309522cb26884bd Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 6 Jul 2017 10:53:32 -0700 Subject: [PATCH 116/159] fix a bug in pivot_fixed_vars_from_basis Signed-off-by: Lev Nachmanson --- src/util/lp/lp_core_solver_base.h | 1 + src/util/lp/lp_core_solver_base.hpp | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/util/lp/lp_core_solver_base.h b/src/util/lp/lp_core_solver_base.h index 925206680..7313a46de 100644 --- a/src/util/lp/lp_core_solver_base.h +++ b/src/util/lp/lp_core_solver_base.h @@ -479,6 +479,7 @@ public: void change_basis(unsigned entering, unsigned leaving) { lean_assert(m_basis_heading[entering] < 0); + lean_assert(m_basis_heading[leaving] >= 0); int place_in_basis = m_basis_heading[leaving]; int place_in_non_basis = - m_basis_heading[entering] - 1; diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp index d551daf27..03ae4e184 100644 --- a/src/util/lp/lp_core_solver_base.hpp +++ b/src/util/lp/lp_core_solver_base.hpp @@ -925,7 +925,9 @@ template void lp_core_solver_base::transpose_row } // j is the new basic column, j_basic - the leaving column template bool lp_core_solver_base::pivot_column_general(unsigned j, unsigned j_basic, indexed_vector & w) { - unsigned row_index = m_basis_heading[j_basic]; + lean_assert(m_basis_heading[j] < 0); + lean_assert(m_basis_heading[j_basic] >= 0); + unsigned row_index = m_basis_heading[j_basic]; change_basis(j, j_basic); if (m_settings.m_simplex_strategy == simplex_strategy_enum::lu) { if (m_factorization->need_to_refactor()) { @@ -940,15 +942,16 @@ template bool lp_core_solver_base::pivot_column_g return false; } } else { // the tableau case - pivot_column_tableau(j, row_index); + return pivot_column_tableau(j, row_index); } - return true; } + template void lp_core_solver_base::pivot_fixed_vars_from_basis() { // run over basis and non-basis at the same time indexed_vector w(m_basis.size()); // the buffer unsigned i = 0; // points to basis unsigned j = 0; // points to nonbasis + for (; i < m_basis.size() && j < m_nbasis.size(); i++) { unsigned ii = m_basis[i]; unsigned jj; @@ -963,8 +966,9 @@ template void lp_core_solver_base::pivot_fixed_v if (j >= m_nbasis.size()) break; j++; - if (!pivot_column_general(jj, ii, w)) - break; + if (!pivot_column_general(jj, ii, w)) + return; // total failure + break; } } } From 2e95a9d6b254ae1555cd47b9737549d1b031c2d4 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 6 Jul 2017 10:59:20 -0700 Subject: [PATCH 117/159] return a value from pivot_column_general Signed-off-by: Lev Nachmanson --- src/util/lp/lp_core_solver_base.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp index 03ae4e184..c2adb61c1 100644 --- a/src/util/lp/lp_core_solver_base.hpp +++ b/src/util/lp/lp_core_solver_base.hpp @@ -944,6 +944,7 @@ template bool lp_core_solver_base::pivot_column_g } else { // the tableau case return pivot_column_tableau(j, row_index); } + return true; } template void lp_core_solver_base::pivot_fixed_vars_from_basis() { From 0e0e9c704121874023289ef0ce33a4d21b648408 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 6 Jul 2017 14:06:33 -0700 Subject: [PATCH 118/159] correct handling of integer vars by NB Signed-off-by: Lev Nachmanson --- src/smt/theory_lra.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 43d3820f3..6144447e3 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -314,6 +314,7 @@ namespace smt { } } + void found_not_handled(expr* n) { m_not_handled = n; if (is_app(n) && is_underspecified(to_app(n))) { @@ -419,9 +420,6 @@ namespace smt { if (is_app(n)) { internalize_args(to_app(n)); } - if (a.is_int(n)) { - found_not_handled(n); - } theory_var v = mk_var(n); coeffs[vars.size()] = coeffs[index]; vars.push_back(v); @@ -1189,6 +1187,7 @@ namespace smt { case l_false: return FC_CONTINUE; case l_undef: + TRACE("arith", tout << "check-lia giveup\n";); st = FC_GIVEUP; break; } @@ -1199,23 +1198,27 @@ namespace smt { case l_false: return FC_CONTINUE; case l_undef: + TRACE("arith", tout << "check-nra giveup\n";); st = FC_GIVEUP; break; } - if (m_not_handled != 0) { + if (m_not_handled != 0) { + TRACE("arith", tout << "unhandled operator " << mk_pp(m_not_handled, m) << "\n";); st = FC_GIVEUP; } - + return st; case l_false: set_conflict(); return FC_CONTINUE; case l_undef: + TRACE("arith", tout << "check feasiable is undef\n";); return m.canceled() ? FC_CONTINUE : FC_GIVEUP; default: UNREACHABLE(); break; } + TRACE("arith", tout << "default giveup\n";); return FC_GIVEUP; } @@ -1268,10 +1271,12 @@ namespace smt { set_conflict1(); return l_false; case lean::lia_move::give_up: + TRACE("arith", tout << "lia giveup\n";); return l_undef; default: UNREACHABLE(); } + UNREACHABLE(); return l_undef; } @@ -1294,6 +1299,8 @@ namespace smt { return l_false; } break; + case l_undef: + TRACE("arith", tout << "nra-undef\n";); default: break; } From d57494395c3929ade7f0fe5454ce249b1357fbc7 Mon Sep 17 00:00:00 2001 From: Daniel Perelman Date: Thu, 6 Jul 2017 16:59:20 -0700 Subject: [PATCH 119/159] Add --guardcf flag to mk_make.py to optionally enable Control Flow Guard. --- scripts/mk_util.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 3ce104709..a5f75fd1c 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -104,6 +104,8 @@ GIT_DESCRIBE=False SLOW_OPTIMIZE=False USE_OMP=True LOG_SYNC=False +GUARD_CF=False +ALWAYS_DYNAMIC_BASE=False FPMATH="Default" FPMATH_FLAGS="-mfpmath=sse -msse -msse2" @@ -623,13 +625,13 @@ def display_help(exit_code): print(" -d, --debug compile Z3 in debug mode.") print(" -t, --trace enable tracing in release mode.") if IS_WINDOWS: + print(" --guardcf enable Control Flow Guard runtime checks.") print(" -x, --x64 create 64 binary when using Visual Studio.") else: print(" --x86 force 32-bit x86 build on x64 systems.") print(" -m, --makefiles generate only makefiles.") if IS_WINDOWS: print(" -v, --vsproj generate Visual Studio Project Files.") - if IS_WINDOWS: print(" --optimize generate optimized code during linking.") print(" --dotnet generate .NET bindings.") print(" --dotnet-key= sign the .NET assembly using the private key in .") @@ -670,10 +672,11 @@ def parse_options(): global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE, VS_PAR, VS_PAR_NUM global DOTNET_ENABLED, DOTNET_KEY_FILE, JAVA_ENABLED, ML_ENABLED, STATIC_LIB, STATIC_BIN, PREFIX, GMP, PYTHON_PACKAGE_DIR, GPROF, GIT_HASH, GIT_DESCRIBE, PYTHON_INSTALL_ENABLED, PYTHON_ENABLED global LINUX_X64, SLOW_OPTIMIZE, USE_OMP, LOG_SYNC + global GUARD_CF, ALWAYS_DYNAMIC_BASE try: options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:df:sxhmcvtnp:gj', - ['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', + ['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', 'guardcf', 'trace', 'dotnet', 'dotnet-key=', 'staticlib', 'prefix=', 'gmp', 'java', 'parallel=', 'gprof', 'githash=', 'git-describe', 'x86', 'ml', 'optimize', 'noomp', 'pypkgdir=', 'python', 'staticbin', 'log-sync']) except: @@ -742,6 +745,9 @@ def parse_options(): elif opt in ('--python'): PYTHON_ENABLED = True PYTHON_INSTALL_ENABLED = True + elif opt == '--guardcf': + GUARD_CF = True + ALWAYS_DYNAMIC_BASE = True # /GUARD:CF requires /DYNAMICBASE else: print("ERROR: Invalid command line option '%s'" % opt) display_help(1) @@ -2310,6 +2316,7 @@ def mk_config(): 'SLINK_OUT_FLAG=/Fe\n' 'OS_DEFINES=/D _WINDOWS\n') extra_opt = '' + link_extra_opt = '' HAS_OMP = test_openmp('cl') if HAS_OMP: extra_opt = ' /openmp' @@ -2319,10 +2326,14 @@ def mk_config(): extra_opt = '%s /DZ3_LOG_SYNC' % extra_opt if GIT_HASH: extra_opt = ' %s /D Z3GITHASH=%s' % (extra_opt, GIT_HASH) + if GUARD_CF: + extra_opt = ' %s /guard:cf' % extra_opt + link_extra_opt = ' %s /GUARD:CF' % link_extra_opt if STATIC_BIN: static_opt = '/MT' else: static_opt = '/MD' + maybe_disable_dynamic_base = '/DYNAMICBASE' if ALWAYS_DYNAMIC_BASE else '/DYNAMICBASE:NO' if DEBUG_MODE: static_opt = static_opt + 'd' config.write( @@ -2333,8 +2344,8 @@ def mk_config(): config.write( 'CXXFLAGS=/c /Zi /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- %s %s\n' % (extra_opt, static_opt)) config.write( - 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' - 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') + 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' + 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (link_extra_opt, maybe_disable_dynamic_base, link_extra_opt)) elif VS_ARM: print("ARM on VS is unsupported") exit(1) @@ -2342,8 +2353,8 @@ def mk_config(): config.write( 'CXXFLAGS=/c /Zi /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2 %s %s\n' % (extra_opt, static_opt)) config.write( - 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' - 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') + 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' + 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (link_extra_opt, maybe_disable_dynamic_base, link_extra_opt)) else: # Windows Release mode LTCG=' /LTCG' if SLOW_OPTIMIZE else '' @@ -2358,8 +2369,8 @@ def mk_config(): config.write( 'CXXFLAGS=/c%s /Zi /nologo /W3 /WX- /O2 /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG /D _LIB /D _WINDOWS /D _AMD64_ /D _UNICODE /D UNICODE /Gm- /EHsc /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TP %s %s\n' % (GL, extra_opt, static_opt)) config.write( - 'LINK_EXTRA_FLAGS=/link%s /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608\n' - 'SLINK_EXTRA_FLAGS=/link%s /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608\n' % (LTCG, LTCG)) + 'LINK_EXTRA_FLAGS=/link%s /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 %s\n' + 'SLINK_EXTRA_FLAGS=/link%s /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 %s\n' % (LTCG, link_extra_opt, LTCG, link_extra_opt)) elif VS_ARM: print("ARM on VS is unsupported") exit(1) @@ -2367,8 +2378,8 @@ def mk_config(): config.write( 'CXXFLAGS=/nologo /c%s /Zi /W3 /WX- /O2 /Oy- /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG /D _CONSOLE /D _WINDOWS /D ASYNC_COMMANDS /Gm- /EHsc /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2 %s %s\n' % (GL, extra_opt, static_opt)) config.write( - 'LINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' - 'SLINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n' % (LTCG, LTCG)) + 'LINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' + 'SLINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (LTCG, link_extra_opt, LTCG, maybe_disable_dynamic_base, link_extra_opt)) From 9b1b096a1694c097ccbfdd7cf17c8ed30681eb4a Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 6 Jul 2017 20:46:17 -0700 Subject: [PATCH 120/159] fix in init_int_int_set Signed-off-by: Lev Nachmanson --- src/util/lp/int_solver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index 1a6d6ddae..ded1d94d8 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -745,7 +745,7 @@ void int_solver::display_column(std::ostream & out, unsigned j) const { bool int_solver::inf_int_set_is_correct() const { for (unsigned j = 0; j < m_lar_solver->A_r().column_count(); j++) { - if (m_inf_int_set.contains(j) != is_int(j) && (!value_is_int(j))) + if (m_inf_int_set.contains(j) != (is_int(j) && (!value_is_int(j)))) return false; } return true; @@ -758,7 +758,7 @@ bool int_solver::column_is_int_inf(unsigned j) const { void int_solver::init_inf_int_set() { m_inf_int_set.clear(); m_inf_int_set.resize(m_lar_solver->A_r().column_count()); - for (unsigned j : m_lar_solver->m_mpq_lar_core_solver.m_r_basis) { + for (unsigned j = 0; j < m_lar_solver->A_r().column_count(); j++) { if (column_is_int_inf(j)) m_inf_int_set.insert(j); } From 055593469ab78cd27689737a4f1aea0a5d58e8dd Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 6 Jul 2017 20:47:07 -0700 Subject: [PATCH 121/159] Dev (#64) * introduce int_solver.h Signed-off-by: Lev Nachmanson * add int_solver class Signed-off-by: Lev Nachmanson * track which var is an integer Signed-off-by: Lev Nachmanson * add queries for integrality of vars Signed-off-by: Lev Nachmanson * resurrect lp_tst in its own director lp Signed-off-by: Lev Nachmanson * add file Signed-off-by: Lev Nachmanson * add_constraint has got a body Signed-off-by: Lev Nachmanson * fix add_constraint and substitute_terms_in_linear_expression Signed-off-by: Lev Nachmanson * after merge with Z3Prover Signed-off-by: Lev Nachmanson * adding stub check_int_feasibility() Signed-off-by: Lev Nachmanson * Dev (#50) * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * small fix in lar_solver.cpp Signed-off-by: Lev Nachmanson * adding some content to the new check_int_feasibility() Signed-off-by: Lev Nachmanson * Dev (#51) * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * adding more nlsat Signed-off-by: Nikolaj Bjorner * nlsat integration Signed-off-by: Nikolaj Bjorner * adding constraints Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * add missing initialization Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * test Signed-off-by: Lev Nachmanson * Dev (#53) * change in a comment Signed-off-by: Lev Nachmanson * Disabled debug output * removing FOCI2 interface from interp * remove foci reference from cmakelist.txt Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * adding more nlsat Signed-off-by: Nikolaj Bjorner * nlsat integration Signed-off-by: Nikolaj Bjorner * adding constraints Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * add missing initialization Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * adding nra Signed-off-by: Nikolaj Bjorner * debugging nra Signed-off-by: Nikolaj Bjorner * updates to nra_solver integration to call it directly from theory_lra instead of over lar_solver Signed-off-by: Nikolaj Bjorner * n/a Signed-off-by: Nikolaj Bjorner * integrate nlsat Signed-off-by: Nikolaj Bjorner * tidy Signed-off-by: Nikolaj Bjorner * preserve is_int flag Signed-off-by: Lev Nachmanson * remove a debug printout Signed-off-by: Lev Nachmanson * Dev (#54) * change in a comment Signed-off-by: Lev Nachmanson * Disabled debug output * removing FOCI2 interface from interp * remove foci reference from cmakelist.txt Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner * adding more nlsat Signed-off-by: Nikolaj Bjorner * nlsat integration Signed-off-by: Nikolaj Bjorner * adding constraints Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * add missing initialization Signed-off-by: Nikolaj Bjorner * adding nra solver Signed-off-by: Nikolaj Bjorner * adding nra Signed-off-by: Nikolaj Bjorner * debugging nra Signed-off-by: Nikolaj Bjorner * updates to nra_solver integration to call it directly from theory_lra instead of over lar_solver Signed-off-by: Nikolaj Bjorner * n/a Signed-off-by: Nikolaj Bjorner * integrate nlsat Signed-off-by: Nikolaj Bjorner * tidy Signed-off-by: Nikolaj Bjorner * use integer test from lra solver, updated it to work on term variables Signed-off-by: Nikolaj Bjorner * fix equality check in assume-eq Signed-off-by: Nikolaj Bjorner * fix model_is_int_feasible Signed-off-by: Lev Nachmanson * untested gcd_test() Signed-off-by: Lev Nachmanson * call fill_explanation_from_fixed_columns() Signed-off-by: Lev Nachmanson * add the call to pivot_fixed_vars_from_basis() to int_solver.cpp::check() Signed-off-by: Lev Nachmanson * port more of theory_arith_int.h Signed-off-by: Lev Nachmanson * use statistics of lar_solver by theory_lra.cpp Signed-off-by: Lev Nachmanson * port more code to int_solver.cpp Signed-off-by: Lev Nachmanson * add an assert Signed-off-by: Lev Nachmanson * more int porting Signed-off-by: Lev Nachmanson * fix a bug in pivot_fixed_vars_from_basis Signed-off-by: Lev Nachmanson * small change Signed-off-by: Lev Nachmanson * implement find_inf_int_base_column() Signed-off-by: Lev Nachmanson * catch unregistered vars in add_var_bound Signed-off-by: Lev Nachmanson * add a file Signed-off-by: Lev Nachmanson * compile for vs2012 Signed-off-by: Lev Nachmanson * fix asserts in add_var_bound Signed-off-by: Lev Nachmanson * fix the lp_solver init when workig on an mps file Signed-off-by: Lev Nachmanson * towards int_solver::check() Signed-off-by: Lev Nachmanson * change in int_solver::check() signature Signed-off-by: Lev Nachmanson * add handlers for lia moves Signed-off-by: Nikolaj Bjorner * spacing Signed-off-by: Nikolaj Bjorner * return branch from int_solver::check() Signed-off-by: Lev Nachmanson * add a stub for mk_gomory_cut Signed-off-by: Lev Nachmanson * Dev (#59) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner * spacing Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * Dev (#60) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner * spacing Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * Dev (#61) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner * spacing Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * more TRACE(arith_int) Signed-off-by: Lev Nachmanson * fix the build Signed-off-by: Lev Nachmanson * loops Signed-off-by: Nikolaj Bjorner * Dev (#62) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner * spacing Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * loops Signed-off-by: Nikolaj Bjorner * build fix Signed-off-by: Lev Nachmanson --- src/util/lp/lp_core_solver_base.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp index c2adb61c1..f3cee7fa8 100644 --- a/src/util/lp/lp_core_solver_base.hpp +++ b/src/util/lp/lp_core_solver_base.hpp @@ -83,8 +83,8 @@ pivot_for_tableau_on_basis() { // i is the pivot row, and j is the pivot column template void lp_core_solver_base:: pivot_to_reduced_costs_tableau(unsigned i, unsigned j) { - if (j >= m_d.size()) - return; + if (j >= m_d.size()) + return; T &a = m_d[j]; if (is_zero(a)) return; @@ -925,9 +925,9 @@ template void lp_core_solver_base::transpose_row } // j is the new basic column, j_basic - the leaving column template bool lp_core_solver_base::pivot_column_general(unsigned j, unsigned j_basic, indexed_vector & w) { - lean_assert(m_basis_heading[j] < 0); - lean_assert(m_basis_heading[j_basic] >= 0); - unsigned row_index = m_basis_heading[j_basic]; + lean_assert(m_basis_heading[j] < 0); + lean_assert(m_basis_heading[j_basic] >= 0); + unsigned row_index = m_basis_heading[j_basic]; change_basis(j, j_basic); if (m_settings.m_simplex_strategy == simplex_strategy_enum::lu) { if (m_factorization->need_to_refactor()) { @@ -952,7 +952,7 @@ template void lp_core_solver_base::pivot_fixed_v indexed_vector w(m_basis.size()); // the buffer unsigned i = 0; // points to basis unsigned j = 0; // points to nonbasis - + for (; i < m_basis.size() && j < m_nbasis.size(); i++) { unsigned ii = m_basis[i]; unsigned jj; @@ -967,9 +967,9 @@ template void lp_core_solver_base::pivot_fixed_v if (j >= m_nbasis.size()) break; j++; - if (!pivot_column_general(jj, ii, w)) - return; // total failure - break; + if (!pivot_column_general(jj, ii, w)) + return; // total failure + break; } } } From 2cd81851e7d1a206abf0121b90dfb1774e4f17d9 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 6 Jul 2017 21:29:09 -0700 Subject: [PATCH 122/159] solve more ilp smt Signed-off-by: Lev Nachmanson --- src/util/lp/int_solver.cpp | 23 ++++++++++--- src/util/lp/int_solver.h | 1 + src/util/lp/lp_core_solver_base.hpp | 52 ++++++++++++++++------------- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index ded1d94d8..30bfcae9b 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -281,9 +281,18 @@ bool int_solver::mk_gomory_cut(unsigned row_index, explanation & ex) { */ } + +void int_solver::init_check_data() { + init_inf_int_set(); + unsigned n = m_lar_solver->A_r().column_count(); + m_old_values_set.resize(n); + m_old_values_data.resize(n); +} + lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { - lean_assert(is_feasible()); - init_inf_int_set(); + lean_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); + lean_assert(is_feasible()); + init_check_data(); lean_assert(inf_int_set_is_correct()); // currently it is a reimplementation of // final_check_status theory_arith::check_int_feasibility() @@ -298,9 +307,12 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { */ m_lar_solver->pivot_fixed_vars_from_basis(); + lean_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); patch_int_infeasible_columns(); - fix_non_base_columns(); - lean_assert(is_feasible()); + lean_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); + fix_non_base_columns(); + lean_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); + lean_assert(is_feasible()); TRACE("arith_int_rows", trace_inf_rows();); if (find_inf_int_base_column() == -1) @@ -339,7 +351,8 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { return lia_move::branch; } } - // return true; + lean_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); + // return true; return lia_move::give_up; } diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index edfba5e5b..8259ae128 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -98,5 +98,6 @@ private: void move_non_base_vars_to_bounds(); void branch_infeasible_int_var(unsigned); bool mk_gomory_cut(unsigned row_index, explanation & ex); + void init_check_data(); }; } diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp index f3cee7fa8..08ba5d251 100644 --- a/src/util/lp/lp_core_solver_base.hpp +++ b/src/util/lp/lp_core_solver_base.hpp @@ -924,27 +924,32 @@ template void lp_core_solver_base::transpose_row m_A.transpose_rows(i, j); } // j is the new basic column, j_basic - the leaving column -template bool lp_core_solver_base::pivot_column_general(unsigned j, unsigned j_basic, indexed_vector & w) { - lean_assert(m_basis_heading[j] < 0); - lean_assert(m_basis_heading[j_basic] >= 0); - unsigned row_index = m_basis_heading[j_basic]; - change_basis(j, j_basic); - if (m_settings.m_simplex_strategy == simplex_strategy_enum::lu) { - if (m_factorization->need_to_refactor()) { - init_lu(); - } else { - m_factorization->prepare_entering(j, w); // to init vector w - m_factorization->replace_column(zero_of_type(), w, row_index); - } - if (m_factorization->get_status() != LU_status::OK) { - change_basis(j_basic, j); - init_lu(); - return false; - } - } else { // the tableau case - return pivot_column_tableau(j, row_index); - } - return true; +template bool lp_core_solver_base::pivot_column_general(unsigned j, unsigned j_basic, indexed_vector & w) { + lean_assert(m_basis_heading[j] < 0); + lean_assert(m_basis_heading[j_basic] >= 0); + unsigned row_index = m_basis_heading[j_basic]; + if (m_settings.m_simplex_strategy == simplex_strategy_enum::lu) { + if (m_factorization->need_to_refactor()) { + init_lu(); + } + else { + m_factorization->prepare_entering(j, w); // to init vector w + m_factorization->replace_column(zero_of_type(), w, row_index); + } + if (m_factorization->get_status() != LU_status::OK) { + init_lu(); + return false; + } + else { + change_basis(j, j_basic); + } + } + else { // the tableau case + if (pivot_column_tableau(j, row_index)) + change_basis(j, j_basic); + else return false; + } + return true; } template void lp_core_solver_base::pivot_fixed_vars_from_basis() { @@ -967,9 +972,8 @@ template void lp_core_solver_base::pivot_fixed_v if (j >= m_nbasis.size()) break; j++; - if (!pivot_column_general(jj, ii, w)) - return; // total failure - break; + if (pivot_column_general(jj, ii, w)) + break; } } } From 49cf3f800836700add36a25fbe69bd2bf8bad9ac Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 7 Jul 2017 07:44:55 -0700 Subject: [PATCH 123/159] update documentation according to #1058 Signed-off-by: Nikolaj Bjorner --- src/api/z3_api.h | 5 ++++- src/tactic/goal.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 386fdd8a2..505302dc1 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -5376,7 +5376,10 @@ extern "C" { /** \brief Add a new formula \c a to the given goal. - Conjunctions are split into separate formulas. + The formula is split according to the following procedure that is applied + until a fixed-point: + Conjunctions are split into separate formulas. + Negations are distributed over disjunctions, resulting in separate formulas. If the goal is \c false, adding new formulas is a no-op. If the formula \c a is \c true, then nothing is added. If the formula \c a is \c false, then the entire goal is replaced by the formula \c false. diff --git a/src/tactic/goal.cpp b/src/tactic/goal.cpp index b14d2676c..a3cac9e2e 100644 --- a/src/tactic/goal.cpp +++ b/src/tactic/goal.cpp @@ -137,7 +137,8 @@ void goal::push_back(expr * f, proof * pr, expr_dependency * d) { } void goal::quick_process(bool save_first, expr_ref& f, expr_dependency * d) { - if (!m().is_and(f) && !(m().is_not(f) && m().is_or(to_app(f)->get_arg(0)))) { + expr* g = 0; + if (!m().is_and(f) && !(m().is_not(f, g) && m().is_or(g))) { if (!save_first) { push_back(f, 0, d); } @@ -170,8 +171,8 @@ void goal::quick_process(bool save_first, expr_ref& f, expr_dependency * d) { todo.push_back(expr_pol(t->get_arg(i), false)); } } - else if (m().is_not(curr)) { - todo.push_back(expr_pol(to_app(curr)->get_arg(0), !pol)); + else if (m().is_not(curr, g)) { + todo.push_back(expr_pol(g, !pol)); } else { if (!pol) { From d06e48a36163934c8058a1d7491c55a26c7e0a49 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 7 Jul 2017 08:13:14 -0700 Subject: [PATCH 124/159] detect overlapping signatures #1134 Signed-off-by: Nikolaj Bjorner --- src/cmd_context/cmd_context.cpp | 26 +++++++++++++++++++++++--- src/cmd_context/cmd_context.h | 1 + 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index d252c3629..6a8b7f79b 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -72,14 +72,34 @@ void func_decls::finalize(ast_manager & m) { m_decls = 0; } +bool func_decls::signatures_collide(func_decl* f, func_decl* g) const { + if (f == g) { + return true; + } + if (f->get_arity() != g->get_arity() || f->get_range() == g->get_range()) { + return false; + } + for (unsigned i = 0; i < f->get_arity(); ++i) { + if (f->get_domain(i) != g->get_domain(i)) + return false; + } + // they have the same type arguments, but different range types. + return true; +} + bool func_decls::contains(func_decl * f) const { if (GET_TAG(m_decls) == 0) { - return UNTAG(func_decl*, m_decls) == f; + func_decl* g = UNTAG(func_decl*, m_decls); + if (!g) return false; + return signatures_collide(f, g); } else { func_decl_set * fs = UNTAG(func_decl_set *, m_decls); - return fs->contains(f); + for (func_decl* g : *fs) { + if (signatures_collide(f, g)) return true; + } } + return false; } bool func_decls::insert(ast_manager & m, func_decl * f) { @@ -661,7 +681,7 @@ void cmd_context::insert(symbol const & s, func_decl * f) { msg += f->get_arity() == 0 ? "constant" : "function"; msg += " '"; msg += s.str(); - msg += "' (with the given signature) already declared"; + msg += "' (with the given signature) already declared with an overlapping signature"; throw cmd_exception(msg.c_str()); } if (s != f->get_name()) { diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index b231e3c82..74b2f3fbc 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -42,6 +42,7 @@ Notes: class func_decls { func_decl * m_decls; + bool signatures_collide(func_decl* f, func_decl* g) const; public: func_decls():m_decls(0) {} func_decls(ast_manager & m, func_decl * f); From ea331ebfbedf47381df1b3fd2ef296c850de3405 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 7 Jul 2017 08:29:16 -0700 Subject: [PATCH 125/159] revert update to #1134 Signed-off-by: Nikolaj Bjorner --- src/cmd_context/cmd_context.cpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 6a8b7f79b..a053fc8e6 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -73,25 +73,13 @@ void func_decls::finalize(ast_manager & m) { } bool func_decls::signatures_collide(func_decl* f, func_decl* g) const { - if (f == g) { - return true; - } - if (f->get_arity() != g->get_arity() || f->get_range() == g->get_range()) { - return false; - } - for (unsigned i = 0; i < f->get_arity(); ++i) { - if (f->get_domain(i) != g->get_domain(i)) - return false; - } - // they have the same type arguments, but different range types. - return true; + return f == g; } bool func_decls::contains(func_decl * f) const { if (GET_TAG(m_decls) == 0) { func_decl* g = UNTAG(func_decl*, m_decls); - if (!g) return false; - return signatures_collide(f, g); + return g && signatures_collide(f, g); } else { func_decl_set * fs = UNTAG(func_decl_set *, m_decls); @@ -681,7 +669,7 @@ void cmd_context::insert(symbol const & s, func_decl * f) { msg += f->get_arity() == 0 ? "constant" : "function"; msg += " '"; msg += s.str(); - msg += "' (with the given signature) already declared with an overlapping signature"; + msg += "' (with the given signature) already declared"; throw cmd_exception(msg.c_str()); } if (s != f->get_name()) { From 3abc7938761f701a3d91b42da6f0509e8430442c Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Fri, 7 Jul 2017 11:47:52 -0700 Subject: [PATCH 126/159] solve more integer smt problems --- src/util/lp/int_solver.cpp | 40 ++++++++++++++++------------- src/util/lp/int_solver.h | 4 +-- src/util/lp/lp_core_solver_base.hpp | 1 + 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index 30bfcae9b..0a5ec6b48 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -11,11 +11,12 @@ void int_solver::fix_non_base_columns() { auto & lcs = m_lar_solver->m_mpq_lar_core_solver; for (unsigned j : lcs.m_r_nbasis) { if (column_is_int_inf(j)) { - set_value(j, floor(lcs.m_r_x[j].x)); + set_value_for_nbasic_column(j, floor(lcs.m_r_x[j].x)); } } if (m_lar_solver->find_feasible_solution() == INFEASIBLE) failed(); + lean_assert(is_feasible() && inf_int_set_is_correct()); } void int_solver::failed() { @@ -307,13 +308,9 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { */ m_lar_solver->pivot_fixed_vars_from_basis(); - lean_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); - patch_int_infeasible_columns(); - lean_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); + patch_int_infeasible_columns(); fix_non_base_columns(); - lean_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); - lean_assert(is_feasible()); - TRACE("arith_int_rows", trace_inf_rows();); + TRACE("arith_int_rows", trace_inf_rows();); if (find_inf_int_base_column() == -1) return lia_move::ok; @@ -363,19 +360,19 @@ void int_solver::move_non_base_vars_to_bounds() { switch (lcs.m_column_types()[j]) { case column_type::boxed: if (val != lcs.m_r_low_bounds()[j] && val != lcs.m_r_upper_bounds()[j]) - set_value(j, lcs.m_r_low_bounds()[j]); + set_value_for_nbasic_column(j, lcs.m_r_low_bounds()[j]); break; case column_type::low_bound: if (val != lcs.m_r_low_bounds()[j]) - set_value(j, lcs.m_r_low_bounds()[j]); + set_value_for_nbasic_column(j, lcs.m_r_low_bounds()[j]); break; case column_type::upper_bound: if (val != lcs.m_r_upper_bounds()[j]) - set_value(j, lcs.m_r_upper_bounds()[j]); + set_value_for_nbasic_column(j, lcs.m_r_upper_bounds()[j]); break; default: if (is_int(j) && !val.is_int()) { - set_value(j, impq(floor(val))); + set_value_for_nbasic_column(j, impq(floor(val))); } } } @@ -383,7 +380,8 @@ void int_solver::move_non_base_vars_to_bounds() { -void int_solver::set_value(unsigned j, const impq & new_val) { +void int_solver::set_value_for_nbasic_column(unsigned j, const impq & new_val) { + lean_assert(!is_base(j)); auto & x = m_lar_solver->m_mpq_lar_core_solver.m_r_x[j]; if (!m_old_values_set.contains(j)) { m_old_values_set.insert(j); @@ -392,7 +390,12 @@ void int_solver::set_value(unsigned j, const impq & new_val) { auto delta = new_val - x; x = new_val; m_lar_solver->change_basic_x_by_delta_on_column(j, delta); - update_column_in_inf_set_set(j); + update_column_in_int_inf_set(j); + auto * it = get_column_iterator(j); + unsigned i; + while (it->next(i)) + update_column_in_int_inf_set(m_lar_solver->m_mpq_lar_core_solver.m_r_basis[i]); + delete it; } void int_solver::patch_int_infeasible_columns() { @@ -425,22 +428,23 @@ void int_solver::patch_int_infeasible_columns() { TRACE("patch_int", tout << "patching with l: " << l << '\n';); - set_value(j, l); + set_value_for_nbasic_column(j, l); } else { TRACE("patch_int", tout << "not patching " << l << "\n";); } } else if (!inf_u) { u = m_is_one? floor(u) : m * floor(u / m); - set_value(j, u); + set_value_for_nbasic_column(j, u); TRACE("patch_int", tout << "patching with u: " << u << '\n';); } else { - set_value(j, impq(0)); + set_value_for_nbasic_column(j, impq(0)); TRACE("patch_int", tout << "patching with 0\n";); } - } + lean_assert(is_feasible() && inf_int_set_is_correct()); + } } mpq get_denominators_lcm(iterator_on_row &it) { @@ -777,7 +781,7 @@ void int_solver::init_inf_int_set() { } } -void int_solver::update_column_in_inf_set_set(unsigned j) { +void int_solver::update_column_in_int_inf_set(unsigned j) { if (is_int(j) && (!value_is_int(j))) m_inf_int_set.insert(j); else diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index 8259ae128..bac99021b 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -81,7 +81,7 @@ private: bool is_base(unsigned j) const; bool is_boxed(unsigned j) const; bool value_is_int(unsigned j) const; - void set_value(unsigned j, const impq & new_val); + void set_value_for_nbasic_column(unsigned j, const impq & new_val); void fix_non_base_columns(); void failed(); bool is_feasible() const; @@ -89,7 +89,7 @@ private: void display_column(std::ostream & out, unsigned j) const; bool inf_int_set_is_correct() const; void init_inf_int_set(); - void update_column_in_inf_set_set(unsigned j); + void update_column_in_int_inf_set(unsigned j); bool column_is_int_inf(unsigned j) const; void trace_inf_rows() const; int find_inf_int_base_column(); diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp index 08ba5d251..f4d7c3770 100644 --- a/src/util/lp/lp_core_solver_base.hpp +++ b/src/util/lp/lp_core_solver_base.hpp @@ -963,6 +963,7 @@ template void lp_core_solver_base::pivot_fixed_v unsigned jj; if (get_column_type(ii) != column_type::fixed) continue; + //todo run over the row here!!!!! while (j < m_nbasis.size()) { for (; j < m_nbasis.size(); j++) { jj = m_nbasis[j]; From f6a75600c29d5a3e6d545d9db7048ad45ad222ff Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Fri, 7 Jul 2017 22:15:47 -0700 Subject: [PATCH 127/159] solve all smt2 from QF_LIA/calypto with int_solver Signed-off-by: Lev Nachmanson --- src/util/lp/int_solver.cpp | 19 +++++-- src/util/lp/lar_core_solver.hpp | 18 +------ src/util/lp/lar_solver.cpp | 4 ++ src/util/lp/lp_core_solver_base.h | 12 +++++ src/util/lp/lp_core_solver_base.hpp | 53 +++++++++++++------ src/util/lp/lp_core_solver_base_instances.cpp | 1 + 6 files changed, 69 insertions(+), 38 deletions(-) diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index 0a5ec6b48..eb31119b9 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -8,15 +8,21 @@ namespace lean { void int_solver::fix_non_base_columns() { + lean_assert(is_feasible() && inf_int_set_is_correct()); auto & lcs = m_lar_solver->m_mpq_lar_core_solver; + bool change = false; for (unsigned j : lcs.m_r_nbasis) { if (column_is_int_inf(j)) { + change = true; set_value_for_nbasic_column(j, floor(lcs.m_r_x[j].x)); } } + if (!change) + return; if (m_lar_solver->find_feasible_solution() == INFEASIBLE) failed(); - lean_assert(is_feasible() && inf_int_set_is_correct()); + init_inf_int_set(); + lean_assert(is_feasible() && inf_int_set_is_correct()); } void int_solver::failed() { @@ -390,8 +396,9 @@ void int_solver::set_value_for_nbasic_column(unsigned j, const impq & new_val) { auto delta = new_val - x; x = new_val; m_lar_solver->change_basic_x_by_delta_on_column(j, delta); - update_column_in_int_inf_set(j); + auto * it = get_column_iterator(j); + update_column_in_int_inf_set(j); unsigned i; while (it->next(i)) update_column_in_int_inf_set(m_lar_solver->m_mpq_lar_core_solver.m_r_basis[i]); @@ -711,7 +718,7 @@ bool int_solver::get_freedom_interval_for_column(unsigned x_j, bool & inf_l, imp else { if (x_i_upper) { impq new_l = x_j_val + ((x_i_val - lcs.m_r_upper_bounds()[x_i]) / a_ij); - set_lower(l, inf_u, new_l); + set_lower(l, inf_l, new_l); if (!inf_l && !inf_u && l == u) break;; } if (x_i_lower) { @@ -730,7 +737,11 @@ bool int_solver::get_freedom_interval_for_column(unsigned x_j, bool & inf_l, imp if (inf_l) tout << "-oo"; else tout << l; tout << "; "; if (inf_u) tout << "oo"; else tout << u; - tout << "]\n";); + tout << "]\n"; + tout << "val = " << get_value(x_j) << "\n"; + ); + lean_assert(inf_l || l <= get_value(x_j)); + lean_assert(inf_u || u >= get_value(x_j)); return true; } diff --git a/src/util/lp/lar_core_solver.hpp b/src/util/lp/lar_core_solver.hpp index a6dd7e3e0..38c522446 100644 --- a/src/util/lp/lar_core_solver.hpp +++ b/src/util/lp/lar_core_solver.hpp @@ -145,23 +145,7 @@ int lar_core_solver::column_is_out_of_bounds(unsigned j) { void lar_core_solver::calculate_pivot_row(unsigned i) { - lean_assert(!m_r_solver.use_tableau()); - lean_assert(m_r_solver.m_pivot_row.is_OK()); - m_r_solver.m_pivot_row_of_B_1.clear(); - m_r_solver.m_pivot_row_of_B_1.resize(m_r_solver.m_m()); - m_r_solver.m_pivot_row.clear(); - m_r_solver.m_pivot_row.resize(m_r_solver.m_n()); - if (m_r_solver.m_settings.use_tableau()) { - unsigned basis_j = m_r_solver.m_basis[i]; - for (auto & c : m_r_solver.m_A.m_rows[i]) { - if (c.m_j != basis_j) - m_r_solver.m_pivot_row.set_value(c.get_val(), c.m_j); - } - return; - } - - m_r_solver.calculate_pivot_row_of_B_1(i); - m_r_solver.calculate_pivot_row_when_pivot_row_of_B1_is_ready(i); + m_r_solver.calculate_pivot_row(i); } diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index def72734c..eff44d1cd 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -648,6 +648,10 @@ void lar_solver::change_basic_x_by_delta_on_column(unsigned j, const numeric_pai m_basic_columns_with_changed_cost.insert(bj); } m_mpq_lar_core_solver.m_r_solver.update_column_in_inf_set(bj); + TRACE("change_x_del", + tout << "changed basis column " << bj << ", it is " << + ( m_mpq_lar_core_solver.m_r_solver.column_is_feasible(bj)? "feas":"inf") << std::endl;); + } } else { m_column_buffer.clear(); diff --git a/src/util/lp/lp_core_solver_base.h b/src/util/lp/lp_core_solver_base.h index 7313a46de..7599a9d2d 100644 --- a/src/util/lp/lp_core_solver_base.h +++ b/src/util/lp/lp_core_solver_base.h @@ -13,6 +13,9 @@ #include "util/lp/lu.h" #include "util/lp/permutation_matrix.h" #include "util/lp/column_namer.h" +#include "util/lp/iterator_on_row.h" +#include "util/lp/iterator_on_pivot_row.h" + namespace lean { template // X represents the type of the x variable and the bounds @@ -688,5 +691,14 @@ public: const unsigned & iters_with_no_cost_growing() const { return m_iters_with_no_cost_growing; } + + linear_combination_iterator * get_iterator_on_row(unsigned i) { + if (m_settings.use_tableau()) + return new iterator_on_row(m_A.m_rows[i]); + calculate_pivot_row(i); + return new iterator_on_pivot_row(m_pivot_row, m_basis[i]); + } + + void calculate_pivot_row(unsigned i); }; } diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp index f4d7c3770..48494d207 100644 --- a/src/util/lp/lp_core_solver_base.hpp +++ b/src/util/lp/lp_core_solver_base.hpp @@ -956,26 +956,23 @@ template void lp_core_solver_base::pivot_fixed_v // run over basis and non-basis at the same time indexed_vector w(m_basis.size()); // the buffer unsigned i = 0; // points to basis - unsigned j = 0; // points to nonbasis - - for (; i < m_basis.size() && j < m_nbasis.size(); i++) { - unsigned ii = m_basis[i]; - unsigned jj; + for (; i < m_basis.size(); i++) { + unsigned basic_j = m_basis[i]; - if (get_column_type(ii) != column_type::fixed) continue; - //todo run over the row here!!!!! - while (j < m_nbasis.size()) { - for (; j < m_nbasis.size(); j++) { - jj = m_nbasis[j]; - if (get_column_type(jj) != column_type::fixed) + if (get_column_type(basic_j) != column_type::fixed) continue; + //todo run over the row here!!!!! call get_iterator_on_row(); + T a; + unsigned j; + auto * it = get_iterator_on_row(i); + while (it->next(a, j)) { + if (j == basic_j) + continue; + if (get_column_type(j) != column_type::fixed) { + if (pivot_column_general(j, basic_j, w)) break; } - if (j >= m_nbasis.size()) - break; - j++; - if (pivot_column_general(jj, ii, w)) - break; - } + } + delete it; } } @@ -1033,4 +1030,26 @@ lp_core_solver_base::infeasibility_cost_is_correct_for_column(unsigned j) } } +template +void lp_core_solver_base::calculate_pivot_row(unsigned i) { + lean_assert(!use_tableau()); + lean_assert(m_pivot_row.is_OK()); + m_pivot_row_of_B_1.clear(); + m_pivot_row_of_B_1.resize(m_m()); + m_pivot_row.clear(); + m_pivot_row.resize(m_n()); + if (m_settings.use_tableau()) { + unsigned basis_j = m_basis[i]; + for (auto & c : m_A.m_rows[i]) { + if (c.m_j != basis_j) + m_pivot_row.set_value(c.get_val(), c.m_j); + } + return; + } + + calculate_pivot_row_of_B_1(i); + calculate_pivot_row_when_pivot_row_of_B1_is_ready(i); +} + + } diff --git a/src/util/lp/lp_core_solver_base_instances.cpp b/src/util/lp/lp_core_solver_base_instances.cpp index 17dcb87db..d473594c8 100644 --- a/src/util/lp/lp_core_solver_base_instances.cpp +++ b/src/util/lp/lp_core_solver_base_instances.cpp @@ -129,3 +129,4 @@ template bool lean::lp_core_solver_base::inf_set_is_correc template bool lean::lp_core_solver_base >::infeasibility_costs_are_correct() const; template bool lean::lp_core_solver_base::infeasibility_costs_are_correct() const; template bool lean::lp_core_solver_base::infeasibility_costs_are_correct() const; +template void lean::lp_core_solver_base >::calculate_pivot_row(unsigned int); From 5714f830b03208d8d47717d22963a4a8395d8364 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 8 Jul 2017 13:37:24 -0700 Subject: [PATCH 128/159] fix check for finite sorts #1122 Signed-off-by: Nikolaj Bjorner --- src/muz/base/rule_properties.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/muz/base/rule_properties.cpp b/src/muz/base/rule_properties.cpp index 518e848c4..247519d63 100644 --- a/src/muz/base/rule_properties.cpp +++ b/src/muz/base/rule_properties.cpp @@ -51,7 +51,8 @@ void rule_properties::collect(rule_set const& rules) { for (unsigned i = 0; m_inf_sort.empty() && i < r->get_decl()->get_arity(); ++i) { sort* d = r->get_decl()->get_domain(i); sort_size sz = d->get_num_elements(); - if (!sz.is_finite()) { + if (!sz.is_finite() && !m_dl.is_rule_sort(d)) { + TRACE("dl", tout << "sort " << mk_pp(d, m) << " is not finite " << sz << "\n";); m_inf_sort.push_back(m_rule); } } From 2af08a378d7759fc0a047125dadd80a295737c56 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 8 Jul 2017 18:21:47 -0700 Subject: [PATCH 129/159] avoid complaining about division by 0 as unhandled in theory-lra Signed-off-by: Nikolaj Bjorner --- src/ast/arith_decl_plugin.h | 2 ++ src/smt/theory_lra.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/ast/arith_decl_plugin.h b/src/ast/arith_decl_plugin.h index beb227c33..6d6da9ed5 100644 --- a/src/ast/arith_decl_plugin.h +++ b/src/ast/arith_decl_plugin.h @@ -275,7 +275,9 @@ public: bool is_uminus(expr const * n) const { return is_app_of(n, m_afid, OP_UMINUS); } bool is_mul(expr const * n) const { return is_app_of(n, m_afid, OP_MUL); } bool is_div(expr const * n) const { return is_app_of(n, m_afid, OP_DIV); } + bool is_div0(expr const * n) const { return is_app_of(n, m_afid, OP_DIV_0); } bool is_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_mod(expr const * n) const { return is_app_of(n, m_afid, OP_MOD); } bool is_rem(expr const * n) const { return is_app_of(n, m_afid, OP_REM); } bool is_to_real(expr const * n) const { return is_app_of(n, m_afid, OP_TO_REAL); } diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 2bd4844e8..9e4f544c1 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -292,6 +292,9 @@ namespace smt { } void found_not_handled(expr* n) { + if (a.is_div0(n)) { + return; + } m_not_handled = n; if (is_app(n) && is_underspecified(to_app(n))) { m_underspecified.push_back(to_app(n)); From 2b0106c199a40500bb661c1afdf7818139ccd1d0 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 9 Jul 2017 11:26:27 +0200 Subject: [PATCH 130/159] doc fixes Signed-off-by: Nikolaj Bjorner --- doc/website.dox.in | 4 +--- src/api/java/Fixedpoint.java | 2 ++ src/api/python/z3/z3.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/website.dox.in b/doc/website.dox.in index 17a8552d1..f8659ec0b 100644 --- a/doc/website.dox.in +++ b/doc/website.dox.in @@ -4,9 +4,7 @@ Z3 is a high-performance theorem prover being developed at Microsoft Research. - The Z3 website moved to http://github.com/z3prover.. - - The old Z3 websites can be found here and here. + The Z3 website is at http://github.com/z3prover.. This website hosts the automatically generated documentation for the Z3 APIs. diff --git a/src/api/java/Fixedpoint.java b/src/api/java/Fixedpoint.java index ad6d5a658..7bb0fda58 100644 --- a/src/api/java/Fixedpoint.java +++ b/src/api/java/Fixedpoint.java @@ -88,6 +88,7 @@ public class Fixedpoint extends Z3Object /** * Add rule into the fixedpoint solver. * + * @param rule implication (Horn clause) representing rule * @param name Nullable rule name. * @throws Z3Exception **/ @@ -178,6 +179,7 @@ public class Fixedpoint extends Z3Object /** * Update named rule into in the fixedpoint solver. * + * @param rule implication (Horn clause) representing rule * @param name Nullable rule name. * @throws Z3Exception **/ diff --git a/src/api/python/z3/z3.py b/src/api/python/z3/z3.py index 52cc2e858..9a1ebccf6 100644 --- a/src/api/python/z3/z3.py +++ b/src/api/python/z3/z3.py @@ -12,7 +12,7 @@ Several online tutorials for Z3Py are available at: http://rise4fun.com/Z3Py/tutorial/guide -Please send feedback, comments and/or corrections to leonardo@microsoft.com. Your comments are very valuable. +Please send feedback, comments and/or corrections on the Issue tracker for https://github.com/Z3prover/z3.git. Your comments are very valuable. Small example: From 6e2ca69654efae9fcddcad755aa5826448f1a8d2 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Sun, 9 Jul 2017 14:21:27 +0100 Subject: [PATCH 131/159] [CMake] Change the `WARNINGS_AS_ERRORS` option from BOOL to STRING to allow a new mode `SERIOUS_ONLY`. Modes: `ON` - All warnings are treated as errors (same as before) `OFF` - Warnings are not treated as errors (same as before) `SERIOUS_ONLY` - A subset of "serious" warnings are treated as errors. Upgrade code is included to upgrade old CMake cache's to use the new type of `WARNINGS_AS_ERRORS`. We should remove it eventually. The user's previous setting is preserved when doing this. Very few warnings are treated as errors for now. Developers can add more later as they see fit. --- README-CMake.md | 12 +++++ cmake/compiler_warnings.cmake | 96 +++++++++++++++++++++++++++++++++-- cmake/z3_add_cxx_flag.cmake | 11 ++-- 3 files changed, 111 insertions(+), 8 deletions(-) diff --git a/README-CMake.md b/README-CMake.md index 7550808fc..715cacad2 100644 --- a/README-CMake.md +++ b/README-CMake.md @@ -266,6 +266,8 @@ The following useful options can be passed to CMake whilst configuring. Disabling this is useful for faster incremental builds. The documentation can be manually built by invoking the ``api_docs`` target. * ``LINK_TIME_OPTIMIZATION`` - BOOL. If set to ``TRUE`` link time optimization will be enabled. * ``API_LOG_SYNC`` - BOOL. If set to ``TRUE`` will enable experimental API log sync feature. +* ``WARNINGS_AS_ERRORS`` - STRING. If set to ``TRUE`` compiler warnings will be treated as errors. If set to ``False`` compiler warnings will not be treated as errors. + If set to ``SERIOUS_ONLY`` a subset of compiler warnings will be treated as errors. On the command line these can be passed to ``cmake`` using the ``-D`` option. In ``ccmake`` and ``cmake-gui`` these can be set in the user interface. @@ -381,3 +383,13 @@ It is tempting use file-globbing in ``CMakeLists.txt`` to find a set for files m use them as the sources to build a target. This however is a bad idea because it prevents CMake from knowing when it needs to rerun itself. This is why source file names are explicitly listed in the ``CMakeLists.txt`` so that when changes are made the source files used to build a target automatically triggers a rerun of CMake. Long story short. Don't use file globbing. + +### Serious warning flags + +By default the `WARNINGS_AS_ERRORS` flag is set to `SERIOUS_ONLY` which means +some warnings will be treated as errors. These warnings are controlled by the +relevant `*_WARNINGS_AS_ERRORS` list defined in +`cmake/compiler_warnings.cmake`. + +Additional warnings should only be added here if the warnings has no false +positives. diff --git a/cmake/compiler_warnings.cmake b/cmake/compiler_warnings.cmake index e02b28b2c..183f490dd 100644 --- a/cmake/compiler_warnings.cmake +++ b/cmake/compiler_warnings.cmake @@ -1,17 +1,61 @@ +################################################################################ +# Compiler warning flags +################################################################################ +# These are passed to relevant compiler provided they are supported set(GCC_AND_CLANG_WARNINGS - "-Wall" + "-Wall" ) set(GCC_ONLY_WARNINGS "") set(CLANG_ONLY_WARNINGS "") set(MSVC_WARNINGS "/W3") +################################################################################ +# Serious warnings +################################################################################ +# This declares the flags that are passed to the compiler when +# `WARNINGS_AS_ERRORS` is set to `SERIOUS_ONLY`. Only flags that are supported +# by the compiler are used. +# +# In effect this a "whitelist" approach where we explicitly tell the compiler +# which warnings we want to be treated as errors. The alternative would be a +# "blacklist" approach where we ask the compiler to treat all warnings are +# treated as errors but then we explicitly list which warnings which should be +# allowed. +# +# The "whitelist" approach seems simpiler because we can incrementally add +# warnings we "think are serious". + +# TODO: Add more warnings that are considered serious enough that we should +# treat them as errors. +set(GCC_AND_CLANG_WARNINGS_AS_ERRORS + # https://clang.llvm.org/docs/DiagnosticsReference.html#wodr + "-Werror=odr" +) +set(GCC_WARNINGS_AS_ERRORS + "" +) +set(CLANG_WARNINGS_AS_ERRORS + # https://clang.llvm.org/docs/DiagnosticsReference.html#wdelete-non-virtual-dtor + "-Werror=delete-non-virtual-dtor" + # https://clang.llvm.org/docs/DiagnosticsReference.html#woverloaded-virtual + "-Werror=overloaded-virtual" +) + +################################################################################ +# Test warning/error flags +################################################################################ set(WARNING_FLAGS_TO_CHECK "") +set(WARNING_AS_ERROR_FLAGS_TO_CHECK "") if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS}) list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_ONLY_WARNINGS}) + list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS_AS_ERRORS}) + list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_WARNINGS_AS_ERRORS}) elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS}) list(APPEND WARNING_FLAGS_TO_CHECK ${CLANG_ONLY_WARNINGS}) + list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS_AS_ERRORS}) + list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${CLANG_WARNINGS_AS_ERRORS}) # FIXME: Remove "x.." when CMP0054 is set to NEW elseif ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") list(APPEND WARNING_FLAGS_TO_CHECK ${MSVC_WARNINGS}) @@ -31,8 +75,40 @@ foreach (flag ${WARNING_FLAGS_TO_CHECK}) z3_add_cxx_flag("${flag}") endforeach() -option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF) -if (WARNINGS_AS_ERRORS) +# TODO: Remove this eventually. +# Detect legacy `WARNINGS_AS_ERRORS` boolean option and covert to new +# to new option type. +get_property( + WARNINGS_AS_ERRORS_CACHE_VAR_TYPE + CACHE + WARNINGS_AS_ERRORS + PROPERTY + TYPE +) +if ("${WARNINGS_AS_ERRORS_CACHE_VAR_TYPE}" STREQUAL "BOOL") + message(WARNING "Detected legacy WARNINGS_AS_ERRORS option. Upgrading") + set(WARNINGS_AS_ERRORS_DEFAULT "${WARNINGS_AS_ERRORS}") + # Delete old entry + unset(WARNINGS_AS_ERRORS CACHE) +else() + set(WARNINGS_AS_ERRORS_DEFAULT "SERIOUS_ONLY") +endif() + +set(WARNINGS_AS_ERRORS + ${WARNINGS_AS_ERRORS_DEFAULT} + CACHE STRING + "Treat warnings as errors. ON, OFF, or SERIOUS_ONLY" +) + # Set GUI options +set_property( + CACHE + WARNINGS_AS_ERRORS + PROPERTY STRINGS + "ON;OFF;SERIOUS_ONLY" +) + +if ("${WARNINGS_AS_ERRORS}" STREQUAL "ON") + message(STATUS "Treating compiler warnings as errors") if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")) list(APPEND Z3_COMPONENT_CXX_FLAGS "-Werror") # FIXME: Remove "x.." when CMP0054 is set to NEW @@ -41,8 +117,14 @@ if (WARNINGS_AS_ERRORS) else() message(AUTHOR_WARNING "Unknown compiler") endif() - message(STATUS "Treating compiler warnings as errors") -else() +elseif ("${WARNINGS_AS_ERRORS}" STREQUAL "SERIOUS_ONLY") + message(STATUS "Treating only serious compiler warnings as errors") + # Loop through the flags + foreach (flag ${WARNING_AS_ERROR_FLAGS_TO_CHECK}) + # Add globally because some flags need to be passed at link time. + z3_add_cxx_flag("${flag}" GLOBAL) + endforeach() +elseif ("${WARNINGS_AS_ERRORS}" STREQUAL "OFF") message(STATUS "Not treating compiler warnings as errors") # FIXME: Remove "x.." when CMP0054 is set to NEW if ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") @@ -51,4 +133,8 @@ else() # build system. list(APPEND Z3_COMPONENT_CXX_FLAGS "/WX-") endif() +else() + message(FATAL_ERROR + "WARNINGS_AS_ERRORS set to unsupported value \"${WARNINGS_AS_ERRORS}\"" + ) endif() diff --git a/cmake/z3_add_cxx_flag.cmake b/cmake/z3_add_cxx_flag.cmake index 6e756d3b9..d2624d890 100644 --- a/cmake/z3_add_cxx_flag.cmake +++ b/cmake/z3_add_cxx_flag.cmake @@ -2,7 +2,7 @@ include(CheckCXXCompilerFlag) include(CMakeParseArguments) function(z3_add_cxx_flag flag) - CMAKE_PARSE_ARGUMENTS(z3_add_flag "REQUIRED" "" "" ${ARGN}) + CMAKE_PARSE_ARGUMENTS(z3_add_flag "REQUIRED;GLOBAL" "" "" ${ARGN}) string(REPLACE "-" "_" SANITIZED_FLAG_NAME "${flag}") string(REPLACE "/" "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}") string(REPLACE "=" "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}") @@ -16,8 +16,13 @@ function(z3_add_cxx_flag flag) endif() if (HAS_${SANITIZED_FLAG_NAME}) message(STATUS "C++ compiler supports ${flag}") - list(APPEND Z3_COMPONENT_CXX_FLAGS "${flag}") - set(Z3_COMPONENT_CXX_FLAGS "${Z3_COMPONENT_CXX_FLAGS}" PARENT_SCOPE) + if (z3_add_flag_GLOBAL) + # Set globally + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag} " PARENT_SCOPE) + else() + list(APPEND Z3_COMPONENT_CXX_FLAGS "${flag}") + set(Z3_COMPONENT_CXX_FLAGS "${Z3_COMPONENT_CXX_FLAGS}" PARENT_SCOPE) + endif() else() message(STATUS "C++ compiler does not support ${flag}") endif() From 630863619b926e1741f195a8ad0b2dd91a4fa4ee Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Sun, 9 Jul 2017 14:41:59 +0100 Subject: [PATCH 132/159] [TravisCI] Add `Z3_WARNINGS_AS_ERRORS` environment variable to control the `WARNINGS_AS_ERRORS` CMake option. --- contrib/ci/Dockerfiles/z3_build.Dockerfile | 2 ++ contrib/ci/README.md | 1 + contrib/ci/scripts/build_z3_cmake.sh | 4 +++- contrib/ci/scripts/travis_ci_linux_entry_point.sh | 7 +++++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/contrib/ci/Dockerfiles/z3_build.Dockerfile b/contrib/ci/Dockerfiles/z3_build.Dockerfile index 8b922edff..2d16d5394 100644 --- a/contrib/ci/Dockerfiles/z3_build.Dockerfile +++ b/contrib/ci/Dockerfiles/z3_build.Dockerfile @@ -28,6 +28,7 @@ ARG Z3_INSTALL_PREFIX=/usr ARG Z3_STATIC_BUILD=0 # Blank default indicates use latest. ARG Z3_SYSTEM_TEST_GIT_REVISION +ARG Z3_WARNINGS_AS_ERRORS=SERIOUS_ONLY ARG Z3_VERBOSE_BUILD_OUTPUT=0 ENV \ @@ -55,6 +56,7 @@ ENV \ Z3_STATIC_BUILD=${Z3_STATIC_BUILD} \ Z3_SYSTEM_TEST_DIR=/home/user/z3_system_test \ Z3_SYSTEM_TEST_GIT_REVISION=${Z3_SYSTEM_TEST_GIT_REVISION} \ + Z3_WARNINGS_AS_ERRORS=${Z3_WARNINGS_AS_ERRORS} \ Z3_INSTALL_PREFIX=${Z3_INSTALL_PREFIX} # We add context across incrementally to maximal cache reuse diff --git a/contrib/ci/README.md b/contrib/ci/README.md index 31bb504b6..2e117c8b1 100644 --- a/contrib/ci/README.md +++ b/contrib/ci/README.md @@ -43,6 +43,7 @@ the future. * `Z3_VERBOSE_BUILD_OUTPUT` - Show compile commands in CMake builds (`0` or `1`) * `Z3_STATIC_BUILD` - Build Z3 binaries and libraries statically (`0` or `1`) * `Z3_SYSTEM_TEST_GIT_REVISION` - Git revision of [z3test](https://github.com/Z3Prover/z3test). If empty lastest revision will be used. +* `Z3_WARNINGS_AS_ERRORS` - Set the `WARNINGS_AS_ERRORS` CMake option pased to Z3 (`OFF`, `ON`, or `SERIOUS_ONLY`) ### Linux diff --git a/contrib/ci/scripts/build_z3_cmake.sh b/contrib/ci/scripts/build_z3_cmake.sh index 98a9724c7..76fd0fb84 100755 --- a/contrib/ci/scripts/build_z3_cmake.sh +++ b/contrib/ci/scripts/build_z3_cmake.sh @@ -20,7 +20,8 @@ set -o pipefail : ${DOTNET_BINDINGS?"DOTNET_BINDINGS must be specified"} : ${JAVA_BINDINGS?"JAVA_BINDINGS must be specified"} : ${USE_LTO?"USE_LTO must be specified"} -: ${Z3_INSTALL_PREFIX?"Z3_INSTALL_PREFIX"} +: ${Z3_INSTALL_PREFIX?"Z3_INSTALL_PREFIX must be specified"} +: ${Z3_WARNINGS_AS_ERRORS?"Z3_WARNINGS_AS_ERRORS must be specified"} ADDITIONAL_Z3_OPTS=() @@ -120,6 +121,7 @@ cmake \ -DCMAKE_BUILD_TYPE=${Z3_BUILD_TYPE} \ -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} \ -DCMAKE_INSTALL_PREFIX=${Z3_INSTALL_PREFIX} \ + -DWARNINGS_AS_ERRORS=${Z3_WARNINGS_AS_ERRORS} \ "${ADDITIONAL_Z3_OPTS[@]}" \ "${Z3_SRC_DIR}" diff --git a/contrib/ci/scripts/travis_ci_linux_entry_point.sh b/contrib/ci/scripts/travis_ci_linux_entry_point.sh index 21b97788f..84b2dd400 100755 --- a/contrib/ci/scripts/travis_ci_linux_entry_point.sh +++ b/contrib/ci/scripts/travis_ci_linux_entry_point.sh @@ -120,6 +120,13 @@ if [ -n "${NO_SUPPRESS_OUTPUT}" ]; then ) fi +if [ -n "${Z3_WARNINGS_AS_ERRORS}" ]; then + BUILD_OPTS+=( \ + "--build-arg" \ + "Z3_WARNINGS_AS_ERRORS=${Z3_WARNINGS_AS_ERRORS}" \ + ) +fi + case ${LINUX_BASE} in ubuntu_14.04) BASE_DOCKER_FILE="${DOCKER_FILE_DIR}/z3_base_ubuntu_14.04.Dockerfile" From cc32e45471c4564d606e574649eefb89af59946f Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 10 Jul 2017 11:06:37 -0700 Subject: [PATCH 133/159] replace lean to lp Signed-off-by: Lev Nachmanson --- src/shell/lp_frontend.cpp | 12 +- src/smt/theory_lra.cpp | 336 ++++++------- src/test/lp/argument_parser.h | 2 +- src/test/lp/lp.cpp | 466 +++++++++--------- src/test/lp/lp_main.cpp | 4 +- src/test/lp/smt_reader.h | 30 +- src/test/lp/test_file_reader.h | 2 +- src/util/lp/binary_heap_priority_queue.h | 4 +- src/util/lp/binary_heap_priority_queue.hpp | 18 +- .../binary_heap_priority_queue_instances.cpp | 6 +- src/util/lp/binary_heap_upair_queue.h | 2 +- src/util/lp/binary_heap_upair_queue.hpp | 8 +- .../lp/binary_heap_upair_queue_instances.cpp | 2 +- src/util/lp/bound_analyzer_on_row.h | 12 +- src/util/lp/bound_propagator.cpp | 2 +- src/util/lp/bound_propagator.h | 4 +- src/util/lp/breakpoint.h | 2 +- src/util/lp/column_info.h | 8 +- src/util/lp/column_namer.h | 2 +- src/util/lp/conversion_helper.h | 2 +- src/util/lp/core_solver_pretty_printer.h | 2 +- src/util/lp/core_solver_pretty_printer.hpp | 8 +- .../core_solver_pretty_printer_instances.cpp | 18 +- src/util/lp/dense_matrix.h | 4 +- src/util/lp/dense_matrix.hpp | 4 +- src/util/lp/dense_matrix_instances.cpp | 32 +- src/util/lp/eta_matrix.h | 4 +- src/util/lp/eta_matrix.hpp | 10 +- src/util/lp/eta_matrix_instances.cpp | 36 +- src/util/lp/hash_helper.h | 4 +- src/util/lp/implied_bound.h | 2 +- src/util/lp/indexed_value.h | 2 +- src/util/lp/indexed_vector.h | 6 +- src/util/lp/indexed_vector.hpp | 6 +- src/util/lp/indexed_vector_instances.cpp | 26 +- src/util/lp/int_set.h | 4 +- src/util/lp/int_solver.cpp | 38 +- src/util/lp/int_solver.h | 2 +- src/util/lp/iterator_on_column.h | 2 +- src/util/lp/iterator_on_indexed_vector.h | 2 +- src/util/lp/iterator_on_pivot_row.h | 2 +- src/util/lp/iterator_on_row.h | 2 +- src/util/lp/iterator_on_term_with_basis_var.h | 2 +- src/util/lp/lar_constraints.h | 6 +- src/util/lp/lar_core_solver.h | 88 ++-- src/util/lp/lar_core_solver.hpp | 36 +- src/util/lp/lar_solution_signature.h | 2 +- src/util/lp/lar_solver.cpp | 282 +++++------ src/util/lp/lar_solver.h | 6 +- src/util/lp/lar_solver_instances.cpp | 2 +- src/util/lp/lar_term.h | 2 +- src/util/lp/linear_combination_iterator.h | 2 +- src/util/lp/lp_core_solver_base.h | 32 +- src/util/lp/lp_core_solver_base.hpp | 74 +-- src/util/lp/lp_core_solver_base_instances.cpp | 224 ++++----- src/util/lp/lp_dual_core_solver.h | 2 +- src/util/lp/lp_dual_core_solver.hpp | 62 +-- src/util/lp/lp_dual_core_solver_instances.cpp | 22 +- src/util/lp/lp_dual_simplex.h | 2 +- src/util/lp/lp_dual_simplex.hpp | 32 +- src/util/lp/lp_dual_simplex_instances.cpp | 8 +- src/util/lp/lp_primal_core_solver.h | 78 +-- src/util/lp/lp_primal_core_solver.hpp | 130 ++--- .../lp/lp_primal_core_solver_instances.cpp | 12 +- src/util/lp/lp_primal_core_solver_tableau.hpp | 52 +- src/util/lp/lp_primal_simplex.h | 2 +- src/util/lp/lp_primal_simplex.hpp | 24 +- src/util/lp/lp_primal_simplex_instances.cpp | 20 +- src/util/lp/lp_settings.h | 4 +- src/util/lp/lp_settings.hpp | 8 +- src/util/lp/lp_settings_instances.cpp | 4 +- src/util/lp/lp_solver.h | 4 +- src/util/lp/lp_solver.hpp | 32 +- src/util/lp/lp_solver_instances.cpp | 68 +-- src/util/lp/lp_utils.cpp | 2 +- src/util/lp/lp_utils.h | 24 +- src/util/lp/lu.h | 14 +- src/util/lp/lu.hpp | 96 ++-- src/util/lp/lu_instances.cpp | 98 ++-- src/util/lp/matrix.h | 2 +- src/util/lp/matrix.hpp | 2 +- src/util/lp/matrix_instances.cpp | 12 +- src/util/lp/mps_reader.h | 18 +- src/util/lp/nra_solver.cpp | 40 +- src/util/lp/nra_solver.h | 10 +- src/util/lp/numeric_pair.h | 30 +- src/util/lp/permutation_matrix.h | 4 +- src/util/lp/permutation_matrix.hpp | 40 +- src/util/lp/permutation_matrix_instances.cpp | 92 ++-- src/util/lp/quick_xplain.cpp | 16 +- src/util/lp/quick_xplain.h | 2 +- src/util/lp/random_updater.h | 2 +- src/util/lp/random_updater.hpp | 38 +- src/util/lp/row_eta_matrix.h | 4 +- src/util/lp/row_eta_matrix.hpp | 16 +- src/util/lp/row_eta_matrix_instances.cpp | 2 +- src/util/lp/scaler.h | 4 +- src/util/lp/scaler.hpp | 8 +- src/util/lp/scaler_instances.cpp | 4 +- src/util/lp/signature_bound_evidence.h | 2 +- src/util/lp/sparse_matrix.h | 18 +- src/util/lp/sparse_matrix.hpp | 96 ++-- src/util/lp/sparse_matrix_instances.cpp | 58 +-- src/util/lp/sparse_vector.h | 4 +- src/util/lp/square_dense_submatrix.h | 22 +- src/util/lp/square_dense_submatrix.hpp | 34 +- .../lp/square_dense_submatrix_instances.cpp | 46 +- src/util/lp/stacked_map.h | 14 +- src/util/lp/stacked_unordered_set.h | 4 +- src/util/lp/stacked_value.h | 2 +- src/util/lp/stacked_vector.h | 22 +- src/util/lp/static_matrix.h | 26 +- src/util/lp/static_matrix.hpp | 36 +- src/util/lp/static_matrix_instances.cpp | 14 +- src/util/lp/tail_matrix.h | 2 +- src/util/lp/test_bound_analyzer.h | 6 +- src/util/lp/ul_pair.h | 2 +- 117 files changed, 1726 insertions(+), 1726 deletions(-) diff --git a/src/shell/lp_frontend.cpp b/src/shell/lp_frontend.cpp index 213f94cb2..694205395 100644 --- a/src/shell/lp_frontend.cpp +++ b/src/shell/lp_frontend.cpp @@ -17,7 +17,7 @@ Author: #include "gparams.h" #include -static lean::lp_solver* g_solver = 0; +static lp::lp_solver* g_solver = 0; static void display_statistics() { if (g_solver && g_solver->settings().print_statistics) { @@ -42,7 +42,7 @@ static void on_timeout() { } } -struct front_end_resource_limit : public lean::lp_resource_limit { +struct front_end_resource_limit : public lp::lp_resource_limit { reslimit& m_reslim; front_end_resource_limit(reslimit& lim): @@ -64,14 +64,14 @@ void run_solver(lp_params & params, char const * mps_file_name) { scoped_timer timer(timeout, &eh); std::string fn(mps_file_name); - lean::mps_reader reader(fn); + lp::mps_reader reader(fn); reader.set_message_stream(&std::cout); // can be redirected reader.read(); if (!reader.is_ok()) { std::cerr << "cannot process " << mps_file_name << std::endl; return; } - lean::lp_solver * solver = reader.create_solver(false); // false - to create the primal solver + lp::lp_solver * solver = reader.create_solver(false); // false - to create the primal solver solver->settings().set_resource_limit(lp_limit); g_solver = solver; if (params.min()) { @@ -80,11 +80,11 @@ void run_solver(lp_params & params, char const * mps_file_name) { solver->settings().set_message_ostream(&std::cout); solver->settings().report_frequency = params.rep_freq(); solver->settings().print_statistics = params.print_stats(); - solver->settings().simplex_strategy() = lean::simplex_strategy_enum::lu; + solver->settings().simplex_strategy() = lp::simplex_strategy_enum::lu; solver->find_maximal_solution(); *(solver->settings().get_message_ostream()) << "status is " << lp_status_to_string(solver->get_status()) << std::endl; - if (solver->get_status() == lean::OPTIMAL) { + if (solver->get_status() == lp::OPTIMAL) { if (params.min()) { solver->flip_costs(); } diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 6144447e3..72654de18 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -40,7 +40,7 @@ Revision History: #include "math/polynomial/algebraic_numbers.h" #include "math/polynomial/polynomial.h" -namespace lp { +namespace lp_api { enum bound_kind { lower_t, upper_t }; std::ostream& operator<<(std::ostream& out, bound_kind const& k) { @@ -118,7 +118,7 @@ namespace lp { namespace smt { - typedef ptr_vector lp_bounds; + typedef ptr_vector lp_bounds; class theory_lra::imp { @@ -137,7 +137,7 @@ namespace smt { delayed_atom(unsigned b, bool t): m_bv(b), m_is_true(t) {} }; - class resource_limit : public lean::lp_resource_limit { + class resource_limit : public lp::lp_resource_limit { imp& m_imp; public: resource_limit(imp& i): m_imp(i) { } @@ -202,13 +202,13 @@ namespace smt { } }; - typedef vector> var_coeffs; + typedef vector> var_coeffs; - svector m_theory_var2var_index; // translate from theory variables to lar vars + svector m_theory_var2var_index; // translate from theory variables to lar vars svector m_var_index2theory_var; // reverse map from lp_solver variables to theory variables svector m_term_index2theory_var; // reverse map from lp_solver variables to theory variables var_coeffs m_left_side; // constraint left side - mutable std::unordered_map m_variable_values; // current model + mutable std::unordered_map m_variable_values; // current model enum constraint_source { inequality_source, @@ -225,10 +225,10 @@ namespace smt { expr* m_not_handled; ptr_vector m_underspecified; unsigned_vector m_var_trail; - vector > m_use_list; // bounds where variables are used. + vector > m_use_list; // bounds where variables are used. // attributes for incremental version: - u_map m_bool_var2bound; + u_map m_bool_var2bound; vector m_bounds; unsigned_vector m_unassigned_bounds; unsigned_vector m_bounds_trail; @@ -247,7 +247,7 @@ namespace smt { scoped_ptr m_a1, m_a2; // integer arithmetic - scoped_ptr m_lia; + scoped_ptr m_lia; struct var_value_eq { @@ -268,7 +268,7 @@ namespace smt { return m_th.is_int(v); } else { - return (unsigned)std::hash()(m_th.get_ivalue(v)); + return (unsigned)std::hash()(m_th.get_ivalue(v)); } } }; @@ -276,9 +276,9 @@ namespace smt { svector m_scopes; - lp::stats m_stats; + lp_api::stats m_stats; arith_factory* m_factory; - scoped_ptr m_solver; + scoped_ptr m_solver; resource_limit m_resource_limit; lp_bounds m_new_bounds; @@ -294,15 +294,15 @@ namespace smt { void init_solver() { if (m_solver) return; lp_params lp(ctx().get_params()); - m_solver = alloc(lean::lar_solver); + m_solver = alloc(lp::lar_solver); m_theory_var2var_index.reset(); m_solver->settings().set_resource_limit(m_resource_limit); - m_solver->settings().simplex_strategy() = static_cast(lp.simplex_strategy()); + m_solver->settings().simplex_strategy() = static_cast(lp.simplex_strategy()); reset_variable_values(); m_solver->settings().bound_propagation() = BP_NONE != propagation_mode(); m_solver->set_propagate_bounds_on_pivoted_rows_mode(lp.bprop_on_pivoted_rows()); //m_solver->settings().set_ostream(0); - m_lia = alloc(lean::int_solver, m_solver.get()); + m_lia = alloc(lp::int_solver, m_solver.get()); } void ensure_nra() { @@ -454,7 +454,7 @@ namespace smt { r = rational::one(); rational r1; v = mk_var(t); - svector vars; + svector vars; ptr_vector todo; todo.push_back(t); while (!todo.empty()) { @@ -556,8 +556,8 @@ namespace smt { return v; } - lean::var_index get_var_index(theory_var v) { - lean::var_index result = UINT_MAX; + lp::var_index get_var_index(theory_var v) { + lp::var_index result = UINT_MAX; if (m_theory_var2var_index.size() > static_cast(v)) { result = m_theory_var2var_index[v]; } @@ -606,20 +606,20 @@ namespace smt { return true; } - void add_eq_constraint(lean::constraint_index index, enode* n1, enode* n2) { + void add_eq_constraint(lp::constraint_index index, enode* n1, enode* n2) { m_constraint_sources.setx(index, equality_source, null_source); m_equalities.setx(index, enode_pair(n1, n2), enode_pair(0, 0)); ++m_stats.m_add_rows; } - void add_ineq_constraint(lean::constraint_index index, literal lit) { + void add_ineq_constraint(lp::constraint_index index, literal lit) { m_constraint_sources.setx(index, inequality_source, null_source); m_inequalities.setx(index, lit, null_literal); ++m_stats.m_add_rows; TRACE("arith", m_solver->print_constraint(index, tout); tout << "\n";); } - void add_def_constraint(lean::constraint_index index, theory_var v) { + void add_def_constraint(lp::constraint_index index, theory_var v) { m_constraint_sources.setx(index, definition_source, null_source); m_definitions.setx(index, v, null_theory_var); ++m_stats.m_add_rows; @@ -634,7 +634,7 @@ namespace smt { st.coeffs().push_back(rational::one()); st.coeffs().push_back(rational::minus_one()); init_left_side(st); - add_eq_constraint(m_solver->add_constraint(m_left_side, lean::EQ, rational::zero()), n1, n2); + add_eq_constraint(m_solver->add_constraint(m_left_side, lp::EQ, rational::zero()), n1, n2); TRACE("arith", tout << "v" << v1 << " = " << "v" << v2 << ": " << mk_pp(n1->get_owner(), m) << " = " << mk_pp(n2->get_owner(), m) << "\n";); @@ -644,7 +644,7 @@ namespace smt { for (unsigned i = m_bounds_trail.size(); i > old_size; ) { --i; unsigned v = m_bounds_trail[i]; - lp::bound* b = m_bounds[v].back(); + lp_api::bound* b = m_bounds[v].back(); // del_use_lists(b); dealloc(b); m_bounds[v].pop_back(); @@ -687,7 +687,7 @@ namespace smt { else { init_left_side(st); theory_var v = mk_var(term); - lean::var_index vi = m_theory_var2var_index.get(v, UINT_MAX); + lp::var_index vi = m_theory_var2var_index.get(v, UINT_MAX); if (vi == UINT_MAX) { vi = m_solver->add_term(m_left_side, st.coeff()); m_theory_var2var_index.setx(v, vi, UINT_MAX); @@ -747,22 +747,22 @@ namespace smt { ctx().set_var_theory(bv, get_id()); expr* n1, *n2; rational r; - lp::bound_kind k; + lp_api::bound_kind k; theory_var v = null_theory_var; if (a.is_le(atom, n1, n2) && is_numeral(n2, r) && is_app(n1)) { v = internalize_def(to_app(n1)); - k = lp::upper_t; + k = lp_api::upper_t; } else if (a.is_ge(atom, n1, n2) && is_numeral(n2, r) && is_app(n1)) { v = internalize_def(to_app(n1)); - k = lp::lower_t; + k = lp_api::lower_t; } else { TRACE("arith", tout << "Could not internalize " << mk_pp(atom, m) << "\n";); found_not_handled(atom); return true; } - lp::bound* b = alloc(lp::bound, bv, v, is_int(v), r, k); + lp_api::bound* b = alloc(lp_api::bound, bv, v, is_int(v), r, k); m_bounds[v].push_back(b); updt_unassigned_bounds(v, +1); m_bounds_trail.push_back(v); @@ -836,7 +836,7 @@ namespace smt { unsigned old_size = m_scopes.size() - num_scopes; del_bounds(m_scopes[old_size].m_bounds_lim); for (unsigned i = m_scopes[old_size].m_var_trail_lim; i < m_var_trail.size(); ++i) { - lean::var_index vi = m_theory_var2var_index[m_var_trail[i]]; + lp::var_index vi = m_theory_var2var_index[m_var_trail[i]]; if (m_solver->is_term(vi)) { unsigned ti = m_solver->adjust_term_index(vi); m_term_index2theory_var[ti] = UINT_MAX; @@ -1027,14 +1027,14 @@ namespace smt { return m_solver->var_is_registered(m_theory_var2var_index[v]); } - lean::impq get_ivalue(theory_var v) const { - lean_assert(can_get_ivalue(v)); - lean::var_index vi = m_theory_var2var_index[v]; + lp::impq get_ivalue(theory_var v) const { + lp_assert(can_get_ivalue(v)); + lp::var_index vi = m_theory_var2var_index[v]; if (!m_solver->is_term(vi)) return m_solver->get_value(vi); - const lean::lar_term& term = m_solver->get_term(vi); - lean::impq result(term.m_v); + const lp::lar_term& term = m_solver->get_term(vi); + lp::impq result(term.m_v); for (const auto & i: term.m_coeffs) { result += m_solver->get_value(i.first) * i.second; } @@ -1044,12 +1044,12 @@ namespace smt { rational get_value(theory_var v) const { if (!can_get_value(v)) return rational::zero(); - lean::var_index vi = m_theory_var2var_index[v]; + lp::var_index vi = m_theory_var2var_index[v]; if (m_variable_values.count(vi) > 0) { return m_variable_values[vi]; } if (m_solver->is_term(vi)) { - const lean::lar_term& term = m_solver->get_term(vi); + const lp::lar_term& term = m_solver->get_term(vi); rational result = term.m_v; for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { result += m_variable_values[i->first] * i->second; @@ -1072,7 +1072,7 @@ namespace smt { } bool assume_eqs() { - svector vars; + svector vars; theory_var sz = static_cast(th.get_num_vars()); for (theory_var v = 0; v < sz; ++v) { if (th.is_relevant_and_shared(get_enode(v))) { @@ -1167,7 +1167,7 @@ namespace smt { final_check_status final_check_eh() { m_use_nra_model = false; lbool is_sat = l_true; - if (m_solver->get_status() != lean::lp_status::OPTIMAL) { + if (m_solver->get_status() != lp::lp_status::OPTIMAL) { is_sat = make_feasible(); } final_check_status st = FC_DONE; @@ -1223,7 +1223,7 @@ namespace smt { } // create a bound atom representing term <= k - app_ref mk_bound(lean::lar_term const& term, rational const& k) { + app_ref mk_bound(lp::lar_term const& term, rational const& k) { SASSERT(k.is_int()); app_ref t = mk_term(term, true); app_ref atom(a.mk_le(t, a.mk_numeral(k, true)), m); @@ -1238,20 +1238,20 @@ namespace smt { lbool check_lia() { if (m.canceled()) return l_undef; - lean::lar_term term; - lean::mpq k; - lean::explanation ex; // TBD, this should be streamlined accross different explanations + lp::lar_term term; + lp::mpq k; + lp::explanation ex; // TBD, this should be streamlined accross different explanations switch(m_lia->check(term, k, ex)) { - case lean::lia_move::ok: + case lp::lia_move::ok: return l_true; - case lean::lia_move::branch: { + case lp::lia_move::branch: { (void)mk_bound(term, k); // branch on term <= k // at this point we have a new unassigned atom that the // SAT core assigns a value to return l_false; } - case lean::lia_move::cut: { + case lp::lia_move::cut: { // m_explanation implies term <= k app_ref b = mk_bound(term, k); m_eqs.reset(); @@ -1265,12 +1265,12 @@ namespace smt { assign(literal(ctx().get_bool_var(b), false)); return l_false; } - case lean::lia_move::conflict: + case lp::lia_move::conflict: // ex contains unsat core m_explanation = ex.m_explanation; set_conflict1(); return l_false; - case lean::lia_move::give_up: + case lp::lia_move::give_up: TRACE("arith", tout << "lia giveup\n";); return l_undef; default: @@ -1375,7 +1375,7 @@ namespace smt { #else propagate_bound(bv, is_true, b); #endif - lp::bound& b = *m_bool_var2bound.find(bv); + lp_api::bound& b = *m_bool_var2bound.find(bv); assert_bound(bv, is_true, b); @@ -1388,7 +1388,7 @@ namespace smt { /*for (; qhead < m_asserted_atoms.size() && !ctx().inconsistent(); ++qhead) { bool_var bv = m_asserted_atoms[qhead].m_bv; bool is_true = m_asserted_atoms[qhead].m_is_true; - lp::bound& b = *m_bool_var2bound.find(bv); + lp_api::bound& b = *m_bool_var2bound.find(bv); propagate_bound_compound(bv, is_true, b); }*/ @@ -1421,7 +1421,7 @@ namespace smt { } int new_num_of_p = m_solver->settings().st().m_num_of_implied_bounds; CTRACE("arith", new_num_of_p > num_of_p, tout << "found " << new_num_of_p << " implied bounds\n";); - if (m_solver->get_status() == lean::lp_status::INFEASIBLE) { + if (m_solver->get_status() == lp::lp_status::INFEASIBLE) { set_conflict(); } else { @@ -1431,7 +1431,7 @@ namespace smt { } } - bool bound_is_interesting(unsigned vi, lean::lconstraint_kind kind, const rational & bval) const { + bool bound_is_interesting(unsigned vi, lp::lconstraint_kind kind, const rational & bval) const { theory_var v; if (m_solver->is_term(vi)) { v = m_term_index2theory_var.get(m_solver->adjust_term_index(vi), null_theory_var); @@ -1448,7 +1448,7 @@ namespace smt { } lp_bounds const& bounds = m_bounds[v]; for (unsigned i = 0; i < bounds.size(); ++i) { - lp::bound* b = bounds[i]; + lp_api::bound* b = bounds[i]; if (ctx().get_assignment(b->get_bv()) != l_undef) { continue; } @@ -1461,11 +1461,11 @@ namespace smt { return false; } - struct local_bound_propagator: public lean::bound_propagator { + struct local_bound_propagator: public lp::bound_propagator { imp & m_imp; local_bound_propagator(imp& i) : bound_propagator(*i.m_solver), m_imp(i) {} - bool bound_is_interesting(unsigned j, lean::lconstraint_kind kind, const rational & v) { + bool bound_is_interesting(unsigned j, lp::lconstraint_kind kind, const rational & v) { return m_imp.bound_is_interesting(j, kind, v); } @@ -1475,10 +1475,10 @@ namespace smt { }; - void propagate_lp_solver_bound(lean::implied_bound& be) { + void propagate_lp_solver_bound(lp::implied_bound& be) { theory_var v; - lean::var_index vi = be.m_j; + lp::var_index vi = be.m_j; if (m_solver->is_term(vi)) { v = m_term_index2theory_var.get(m_solver->adjust_term_index(vi), null_theory_var); } @@ -1499,7 +1499,7 @@ namespace smt { lp_bounds const& bounds = m_bounds[v]; bool first = true; for (unsigned i = 0; i < bounds.size(); ++i) { - lp::bound* b = bounds[i]; + lp_api::bound* b = bounds[i]; if (ctx().get_assignment(b->get_bv()) != l_undef) { continue; } @@ -1562,28 +1562,28 @@ namespace smt { } } - literal is_bound_implied(lean::lconstraint_kind k, rational const& value, lp::bound const& b) const { - if ((k == lean::LE || k == lean::LT) && b.get_bound_kind() == lp::upper_t && value <= b.get_value()) { + literal is_bound_implied(lp::lconstraint_kind k, rational const& value, lp_api::bound const& b) const { + if ((k == lp::LE || k == lp::LT) && b.get_bound_kind() == lp_api::upper_t && value <= b.get_value()) { // v <= value <= b.get_value() => v <= b.get_value() return literal(b.get_bv(), false); } - if ((k == lean::GE || k == lean::GT) && b.get_bound_kind() == lp::lower_t && b.get_value() <= value) { + if ((k == lp::GE || k == lp::GT) && b.get_bound_kind() == lp_api::lower_t && b.get_value() <= value) { // b.get_value() <= value <= v => b.get_value() <= v return literal(b.get_bv(), false); } - if (k == lean::LE && b.get_bound_kind() == lp::lower_t && value < b.get_value()) { + if (k == lp::LE && b.get_bound_kind() == lp_api::lower_t && value < b.get_value()) { // v <= value < b.get_value() => v < b.get_value() return literal(b.get_bv(), true); } - if (k == lean::LT && b.get_bound_kind() == lp::lower_t && value <= b.get_value()) { + if (k == lp::LT && b.get_bound_kind() == lp_api::lower_t && value <= b.get_value()) { // v < value <= b.get_value() => v < b.get_value() return literal(b.get_bv(), true); } - if (k == lean::GE && b.get_bound_kind() == lp::upper_t && b.get_value() < value) { + if (k == lp::GE && b.get_bound_kind() == lp_api::upper_t && b.get_value() < value) { // b.get_value() < value <= v => b.get_value() < v return literal(b.get_bv(), true); } - if (k == lean::GT && b.get_bound_kind() == lp::upper_t && b.get_value() <= value) { + if (k == lp::GT && b.get_bound_kind() == lp_api::upper_t && b.get_value() <= value) { // b.get_value() <= value < v => b.get_value() < v return literal(b.get_bv(), true); } @@ -1591,7 +1591,7 @@ namespace smt { return null_literal; } - void mk_bound_axioms(lp::bound& b) { + void mk_bound_axioms(lp_api::bound& b) { if (!ctx().is_searching()) { // // NB. We make an assumption that user push calls propagation @@ -1602,19 +1602,19 @@ namespace smt { return; } theory_var v = b.get_var(); - lp::bound_kind kind1 = b.get_bound_kind(); + lp_api::bound_kind kind1 = b.get_bound_kind(); rational const& k1 = b.get_value(); lp_bounds & bounds = m_bounds[v]; - lp::bound* end = 0; - lp::bound* lo_inf = end, *lo_sup = end; - lp::bound* hi_inf = end, *hi_sup = end; + lp_api::bound* end = 0; + lp_api::bound* lo_inf = end, *lo_sup = end; + lp_api::bound* hi_inf = end, *hi_sup = end; for (unsigned i = 0; i < bounds.size(); ++i) { - lp::bound& other = *bounds[i]; + lp_api::bound& other = *bounds[i]; if (&other == &b) continue; if (b.get_bv() == other.get_bv()) continue; - lp::bound_kind kind2 = other.get_bound_kind(); + lp_api::bound_kind kind2 = other.get_bound_kind(); rational const& k2 = other.get_value(); if (k1 == k2 && kind1 == kind2) { // the bounds are equivalent. @@ -1622,7 +1622,7 @@ namespace smt { } SASSERT(k1 != k2 || kind1 != kind2); - if (kind2 == lp::lower_t) { + if (kind2 == lp_api::lower_t) { if (k2 < k1) { if (lo_inf == end || k2 > lo_inf->get_value()) { lo_inf = &other; @@ -1648,14 +1648,14 @@ namespace smt { } - void mk_bound_axiom(lp::bound& b1, lp::bound& b2) { + void mk_bound_axiom(lp_api::bound& b1, lp_api::bound& b2) { theory_var v = b1.get_var(); literal l1(b1.get_bv()); literal l2(b2.get_bv()); rational const& k1 = b1.get_value(); rational const& k2 = b2.get_value(); - lp::bound_kind kind1 = b1.get_bound_kind(); - lp::bound_kind kind2 = b2.get_bound_kind(); + lp_api::bound_kind kind1 = b1.get_bound_kind(); + lp_api::bound_kind kind2 = b2.get_bound_kind(); bool v_is_int = is_int(v); SASSERT(v == b2.get_var()); if (k1 == k2 && kind1 == kind2) return; @@ -1663,8 +1663,8 @@ namespace smt { parameter coeffs[3] = { parameter(symbol("farkas")), parameter(rational(1)), parameter(rational(1)) }; - if (kind1 == lp::lower_t) { - if (kind2 == lp::lower_t) { + if (kind1 == lp_api::lower_t) { + if (kind2 == lp_api::lower_t) { if (k2 <= k1) { mk_clause(~l1, l2, 3, coeffs); } @@ -1685,7 +1685,7 @@ namespace smt { } } } - else if (kind2 == lp::lower_t) { + else if (kind2 == lp_api::lower_t) { if (k1 >= k2) { // k1 >= lo_inf, k1 >= x or lo_inf <= x mk_clause(l1, l2, 3, coeffs); @@ -1743,21 +1743,21 @@ namespace smt { iterator begin1 = occs.begin(); iterator begin2 = occs.begin(); iterator end = occs.end(); - begin1 = first(lp::lower_t, begin1, end); - begin2 = first(lp::upper_t, begin2, end); + begin1 = first(lp_api::lower_t, begin1, end); + begin2 = first(lp_api::upper_t, begin2, end); iterator lo_inf = begin1, lo_sup = begin1; iterator hi_inf = begin2, hi_sup = begin2; iterator lo_inf1 = begin1, lo_sup1 = begin1; iterator hi_inf1 = begin2, hi_sup1 = begin2; bool flo_inf, fhi_inf, flo_sup, fhi_sup; - ptr_addr_hashtable visited; + ptr_addr_hashtable visited; for (unsigned i = 0; i < atoms.size(); ++i) { - lp::bound* a1 = atoms[i]; - lo_inf1 = next_inf(a1, lp::lower_t, lo_inf, end, flo_inf); - hi_inf1 = next_inf(a1, lp::upper_t, hi_inf, end, fhi_inf); - lo_sup1 = next_sup(a1, lp::lower_t, lo_sup, end, flo_sup); - hi_sup1 = next_sup(a1, lp::upper_t, hi_sup, end, fhi_sup); + lp_api::bound* a1 = atoms[i]; + lo_inf1 = next_inf(a1, lp_api::lower_t, lo_inf, end, flo_inf); + hi_inf1 = next_inf(a1, lp_api::upper_t, hi_inf, end, fhi_inf); + lo_sup1 = next_sup(a1, lp_api::lower_t, lo_sup, end, flo_sup); + hi_sup1 = next_sup(a1, lp_api::upper_t, hi_sup, end, fhi_sup); if (lo_inf1 != end) lo_inf = lo_inf1; if (lo_sup1 != end) lo_sup = lo_sup1; if (hi_inf1 != end) hi_inf = hi_inf1; @@ -1776,24 +1776,24 @@ namespace smt { } struct compare_bounds { - bool operator()(lp::bound* a1, lp::bound* a2) const { return a1->get_value() < a2->get_value(); } + bool operator()(lp_api::bound* a1, lp_api::bound* a2) const { return a1->get_value() < a2->get_value(); } }; lp_bounds::iterator first( - lp::bound_kind kind, + lp_api::bound_kind kind, iterator it, iterator end) { for (; it != end; ++it) { - lp::bound* a = *it; + lp_api::bound* a = *it; if (a->get_bound_kind() == kind) return it; } return end; } lp_bounds::iterator next_inf( - lp::bound* a1, - lp::bound_kind kind, + lp_api::bound* a1, + lp_api::bound_kind kind, iterator it, iterator end, bool& found_compatible) { @@ -1801,7 +1801,7 @@ namespace smt { iterator result = end; found_compatible = false; for (; it != end; ++it) { - lp::bound * a2 = *it; + lp_api::bound * a2 = *it; if (a1 == a2) continue; if (a2->get_bound_kind() != kind) continue; rational const & k2(a2->get_value()); @@ -1817,15 +1817,15 @@ namespace smt { } lp_bounds::iterator next_sup( - lp::bound* a1, - lp::bound_kind kind, + lp_api::bound* a1, + lp_api::bound_kind kind, iterator it, iterator end, bool& found_compatible) { rational const & k1(a1->get_value()); found_compatible = false; for (; it != end; ++it) { - lp::bound * a2 = *it; + lp_api::bound * a2 = *it; if (a1 == a2) continue; if (a2->get_bound_kind() != kind) continue; rational const & k2(a2->get_value()); @@ -1839,7 +1839,7 @@ namespace smt { void propagate_basic_bounds() { for (auto const& bv : m_to_check) { - lp::bound& b = *m_bool_var2bound.find(bv); + lp_api::bound& b = *m_bool_var2bound.find(bv); propagate_bound(bv, ctx().get_assignment(bv) == l_true, b); if (ctx().inconsistent()) break; @@ -1854,11 +1854,11 @@ namespace smt { // x <= hi -> x <= hi' // x <= hi -> ~(x >= hi') - void propagate_bound(bool_var bv, bool is_true, lp::bound& b) { + void propagate_bound(bool_var bv, bool is_true, lp_api::bound& b) { if (BP_NONE == propagation_mode()) { return; } - lp::bound_kind k = b.get_bound_kind(); + lp_api::bound_kind k = b.get_bound_kind(); theory_var v = b.get_var(); inf_rational val = b.get_value(is_true); lp_bounds const& bounds = m_bounds[v]; @@ -1868,12 +1868,12 @@ namespace smt { literal lit1(bv, !is_true); literal lit2 = null_literal; - bool find_glb = (is_true == (k == lp::lower_t)); + bool find_glb = (is_true == (k == lp_api::lower_t)); if (find_glb) { rational glb; - lp::bound* lb = 0; + lp_api::bound* lb = 0; for (unsigned i = 0; i < bounds.size(); ++i) { - lp::bound* b2 = bounds[i]; + lp_api::bound* b2 = bounds[i]; if (b2 == &b) continue; rational const& val2 = b2->get_value(); if ((is_true ? val2 < val : val2 <= val) && (!lb || glb < val2)) { @@ -1882,14 +1882,14 @@ namespace smt { } } if (!lb) return; - bool sign = lb->get_bound_kind() != lp::lower_t; + bool sign = lb->get_bound_kind() != lp_api::lower_t; lit2 = literal(lb->get_bv(), sign); } else { rational lub; - lp::bound* ub = 0; + lp_api::bound* ub = 0; for (unsigned i = 0; i < bounds.size(); ++i) { - lp::bound* b2 = bounds[i]; + lp_api::bound* b2 = bounds[i]; if (b2 == &b) continue; rational const& val2 = b2->get_value(); if ((is_true ? val < val2 : val <= val2) && (!ub || val2 < lub)) { @@ -1898,7 +1898,7 @@ namespace smt { } } if (!ub) return; - bool sign = ub->get_bound_kind() != lp::upper_t; + bool sign = ub->get_bound_kind() != lp_api::upper_t; lit2 = literal(ub->get_bv(), sign); } TRACE("arith", @@ -1918,27 +1918,27 @@ namespace smt { ++m_stats.m_bounds_propagations; } - void add_use_lists(lp::bound* b) { + void add_use_lists(lp_api::bound* b) { theory_var v = b->get_var(); - lean::var_index vi = get_var_index(v); + lp::var_index vi = get_var_index(v); if (m_solver->is_term(vi)) { - lean::lar_term const& term = m_solver->get_term(vi); + lp::lar_term const& term = m_solver->get_term(vi); for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { - lean::var_index wi = i->first; + lp::var_index wi = i->first; unsigned w = m_var_index2theory_var[wi]; - m_use_list.reserve(w + 1, ptr_vector()); + m_use_list.reserve(w + 1, ptr_vector()); m_use_list[w].push_back(b); } } } - void del_use_lists(lp::bound* b) { + void del_use_lists(lp_api::bound* b) { theory_var v = b->get_var(); - lean::var_index vi = m_theory_var2var_index[v]; + lp::var_index vi = m_theory_var2var_index[v]; if (m_solver->is_term(vi)) { - lean::lar_term const& term = m_solver->get_term(vi); + lp::lar_term const& term = m_solver->get_term(vi); for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { - lean::var_index wi = i->first; + lp::var_index wi = i->first; unsigned w = m_var_index2theory_var[wi]; SASSERT(m_use_list[w].back() == b); m_use_list[w].pop_back(); @@ -1952,7 +1952,7 @@ namespace smt { // have been assigned we may know the truth value of the inequality by using simple // bounds propagation. // - void propagate_bound_compound(bool_var bv, bool is_true, lp::bound& b) { + void propagate_bound_compound(bool_var bv, bool is_true, lp_api::bound& b) { theory_var v = b.get_var(); TRACE("arith", tout << mk_pp(get_owner(v), m) << "\n";); if (static_cast(v) >= m_use_list.size()) { @@ -1968,7 +1968,7 @@ namespace smt { // x >= 0, y >= 1 -> x + y >= 1 // x <= 0, y <= 2 -> x + y <= 2 literal lit = null_literal; - if (lp::lower_t == vb->get_bound_kind()) { + if (lp_api::lower_t == vb->get_bound_kind()) { if (get_glb(*vb, r) && r >= vb->get_value()) { // vb is assigned true lit = literal(vb->get_bv(), false); } @@ -2002,30 +2002,30 @@ namespace smt { } } - bool get_lub(lp::bound const& b, inf_rational& lub) { + bool get_lub(lp_api::bound const& b, inf_rational& lub) { return get_bound(b, lub, true); } - bool get_glb(lp::bound const& b, inf_rational& glb) { + bool get_glb(lp_api::bound const& b, inf_rational& glb) { return get_bound(b, glb, false); } - std::ostream& display_bound(std::ostream& out, lp::bound const& b) { + std::ostream& display_bound(std::ostream& out, lp_api::bound const& b) { return out << mk_pp(ctx().bool_var2expr(b.get_bv()), m); } - bool get_bound(lp::bound const& b, inf_rational& r, bool is_lub) { + bool get_bound(lp_api::bound const& b, inf_rational& r, bool is_lub) { m_core.reset(); m_eqs.reset(); m_params.reset(); r.reset(); theory_var v = b.get_var(); - lean::var_index vi = m_theory_var2var_index[v]; + lp::var_index vi = m_theory_var2var_index[v]; SASSERT(m_solver->is_term(vi)); - lean::lar_term const& term = m_solver->get_term(vi); + lp::lar_term const& term = m_solver->get_term(vi); for (auto const coeff : term.m_coeffs) { - lean::var_index wi = coeff.first; - lean::constraint_index ci; + lp::var_index wi = coeff.first; + lp::constraint_index ci; rational value; bool is_strict; if (coeff.second.is_neg() == is_lub) { @@ -2052,25 +2052,25 @@ namespace smt { return true; } - void assert_bound(bool_var bv, bool is_true, lp::bound& b) { - if (m_solver->get_status() == lean::lp_status::INFEASIBLE) { + void assert_bound(bool_var bv, bool is_true, lp_api::bound& b) { + if (m_solver->get_status() == lp::lp_status::INFEASIBLE) { return; } scoped_internalize_state st(*this); st.vars().push_back(b.get_var()); st.coeffs().push_back(rational::one()); init_left_side(st); - lean::lconstraint_kind k = lean::EQ; + lp::lconstraint_kind k = lp::EQ; bool is_int = b.is_int(); switch (b.get_bound_kind()) { - case lp::lower_t: - k = is_true ? lean::GE : (is_int ? lean::LE : lean::LT); + case lp_api::lower_t: + k = is_true ? lp::GE : (is_int ? lp::LE : lp::LT); break; - case lp::upper_t: - k = is_true ? lean::LE : (is_int ? lean::GE : lean::GT); + case lp_api::upper_t: + k = is_true ? lp::LE : (is_int ? lp::GE : lp::GT); break; } - if (k == lean::LT || k == lean::LE) { + if (k == lp::LT || k == lp::LE) { ++m_stats.m_assert_lower; } else { @@ -2078,7 +2078,7 @@ namespace smt { } auto vi = get_var_index(b.get_var()); rational bound = b.get_value(); - lean::constraint_index ci; + lp::constraint_index ci; if (is_int && !is_true) { rational bound = b.get_value(false).get_rational(); ci = m_solver->add_var_bound(vi, k, bound); @@ -2099,7 +2099,7 @@ namespace smt { // Then the equality v1 == v2 is propagated to the core. // - typedef std::pair constraint_bound; + typedef std::pair constraint_bound; vector m_lower_terms; vector m_upper_terms; typedef std::pair value_sort_pair; @@ -2107,16 +2107,16 @@ namespace smt { typedef map > value2var; value2var m_fixed_var_table; - void propagate_eqs(lean::var_index vi, lean::constraint_index ci, lean::lconstraint_kind k, lp::bound& b) { + void propagate_eqs(lp::var_index vi, lp::constraint_index ci, lp::lconstraint_kind k, lp_api::bound& b) { if (propagate_eqs()) { rational const& value = b.get_value(); - if (k == lean::GE) { + if (k == lp::GE) { set_lower_bound(vi, ci, value); if (has_upper_bound(vi, ci, value)) { fixed_var_eh(b.get_var(), value); } } - else if (k == lean::LE) { + else if (k == lp::LE) { set_upper_bound(vi, ci, value); if (has_lower_bound(vi, ci, value)) { fixed_var_eh(b.get_var(), value); @@ -2137,16 +2137,16 @@ namespace smt { bool use_tableau() const { return lp_params(ctx().get_params()).simplex_strategy() < 2; } - void set_upper_bound(lean::var_index vi, lean::constraint_index ci, rational const& v) { set_bound(vi, ci, v, false); } + void set_upper_bound(lp::var_index vi, lp::constraint_index ci, rational const& v) { set_bound(vi, ci, v, false); } - void set_lower_bound(lean::var_index vi, lean::constraint_index ci, rational const& v) { set_bound(vi, ci, v, true); } + void set_lower_bound(lp::var_index vi, lp::constraint_index ci, rational const& v) { set_bound(vi, ci, v, true); } - void set_bound(lean::var_index vi, lean::constraint_index ci, rational const& v, bool is_lower) { + void set_bound(lp::var_index vi, lp::constraint_index ci, rational const& v, bool is_lower) { if (!m_solver->is_term(vi)) { // m_solver already tracks bounds on proper variables, but not on terms. return; } - lean::var_index ti = m_solver->adjust_term_index(vi); + lp::var_index ti = m_solver->adjust_term_index(vi); auto& vec = is_lower ? m_lower_terms : m_upper_terms; if (vec.size() <= ti) { vec.resize(ti + 1, constraint_bound(UINT_MAX, rational())); @@ -2159,15 +2159,15 @@ namespace smt { } } - bool has_upper_bound(lean::var_index vi, lean::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, false); } + bool has_upper_bound(lp::var_index vi, lp::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, false); } - bool has_lower_bound(lean::var_index vi, lean::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, true); } + bool has_lower_bound(lp::var_index vi, lp::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, true); } - bool has_bound(lean::var_index vi, lean::constraint_index& ci, rational const& bound, bool is_lower) { + bool has_bound(lp::var_index vi, lp::constraint_index& ci, rational const& bound, bool is_lower) { if (m_solver->is_term(vi)) { - lean::var_index ti = m_solver->adjust_term_index(vi); + lp::var_index ti = m_solver->adjust_term_index(vi); theory_var v = m_term_index2theory_var.get(ti, null_theory_var); rational val; TRACE("arith", tout << vi << " " << v << "\n";); @@ -2210,7 +2210,7 @@ namespace smt { if (static_cast(v2) < th.get_num_vars() && !is_equal(v1, v2)) { auto vi1 = get_var_index(v1); auto vi2 = get_var_index(v2); - lean::constraint_index ci1, ci2, ci3, ci4; + lp::constraint_index ci1, ci2, ci3, ci4; TRACE("arith", tout << "fixed: " << mk_pp(get_owner(v1), m) << " " << mk_pp(get_owner(v2), m) << " " << bound << " " << has_lower_bound(vi2, ci3, bound) << "\n";); if (has_lower_bound(vi2, ci3, bound) && has_upper_bound(vi2, ci4, bound)) { VERIFY (has_lower_bound(vi1, ci1, bound)); @@ -2260,13 +2260,13 @@ namespace smt { auto status = m_solver->find_feasible_solution(); TRACE("arith_verbose", display(tout);); switch (status) { - case lean::lp_status::INFEASIBLE: + case lp::lp_status::INFEASIBLE: return l_false; - case lean::lp_status::FEASIBLE: - case lean::lp_status::OPTIMAL: + case lp::lp_status::FEASIBLE: + case lp::lp_status::OPTIMAL: // SASSERT(m_solver->all_constraints_hold()); return l_true; - case lean::lp_status::TIME_EXHAUSTED: + case lp::lp_status::TIME_EXHAUSTED: default: TRACE("arith", tout << "status treated as inconclusive: " << status << "\n";); @@ -2276,14 +2276,14 @@ namespace smt { } } - vector> m_explanation; + vector> m_explanation; literal_vector m_core; svector m_eqs; vector m_params; - // lean::constraint_index const null_constraint_index = UINT_MAX; // not sure what a correct fix is + // lp::constraint_index const null_constraint_index = UINT_MAX; // not sure what a correct fix is - void set_evidence(lean::constraint_index idx) { + void set_evidence(lp::constraint_index idx) { if (idx == UINT_MAX) { return; } @@ -2371,14 +2371,14 @@ namespace smt { nlsat::anum const& nl_value(theory_var v, scoped_anum& r) { SASSERT(m_nra); SASSERT(m_use_nra_model); - lean::var_index vi = m_theory_var2var_index[v]; + lp::var_index vi = m_theory_var2var_index[v]; if (m_solver->is_term(vi)) { - lean::lar_term const& term = m_solver->get_term(vi); + lp::lar_term const& term = m_solver->get_term(vi); scoped_anum r1(m_nra->am()); m_nra->am().set(r, term.m_v.to_mpq()); for (auto const coeff : term.m_coeffs) { - lean::var_index wi = coeff.first; + lp::var_index wi = coeff.first; m_nra->am().set(r1, coeff.second.to_mpq()); m_nra->am().mul(m_nra->value(wi), r1, r1); m_nra->am().add(r1, r, r); @@ -2474,16 +2474,16 @@ namespace smt { } theory_lra::inf_eps value(theory_var v) { - lean::impq ival = get_ivalue(v); + lp::impq ival = get_ivalue(v); return inf_eps(0, inf_rational(ival.x, ival.y)); } theory_lra::inf_eps maximize(theory_var v, expr_ref& blocker, bool& has_shared) { - lean::var_index vi = m_theory_var2var_index.get(v, UINT_MAX); - vector > coeffs; + lp::var_index vi = m_theory_var2var_index.get(v, UINT_MAX); + vector > coeffs; rational coeff; if (m_solver->is_term(vi)) { - const lean::lar_term& term = m_solver->get_term(vi); + const lp::lar_term& term = m_solver->get_term(vi); for (auto & ti : term.m_coeffs) { coeffs.push_back(std::make_pair(ti.second, ti.first)); } @@ -2493,7 +2493,7 @@ namespace smt { coeffs.push_back(std::make_pair(rational::one(), vi)); coeff = rational::zero(); } - lean::impq term_max; + lp::impq term_max; if (m_solver->maximize_term(coeffs, term_max)) { blocker = mk_gt(v); inf_rational val(term_max.x + coeff, term_max.y); @@ -2508,7 +2508,7 @@ namespace smt { } expr_ref mk_gt(theory_var v) { - lean::impq val = get_ivalue(v); + lp::impq val = get_ivalue(v); expr* obj = get_enode(v)->get_owner(); rational r = val.x; expr_ref e(m); @@ -2539,7 +2539,7 @@ namespace smt { return internalize_def(term); } - app_ref mk_term(lean::lar_term const& term, bool is_int) { + app_ref mk_term(lp::lar_term const& term, bool is_int) { expr_ref_vector args(m); for (auto & ti : term.m_coeffs) { theory_var w = m_var_index2theory_var[ti.first]; @@ -2561,7 +2561,7 @@ namespace smt { } app_ref mk_obj(theory_var v) { - lean::var_index vi = m_theory_var2var_index[v]; + lp::var_index vi = m_theory_var2var_index[v]; bool is_int = a.is_int(get_enode(v)->get_owner()); if (m_solver->is_term(vi)) { return mk_term(m_solver->get_term(vi), is_int); @@ -2588,9 +2588,9 @@ namespace smt { bool_var bv = ctx().mk_bool_var(b); ctx().set_var_theory(bv, get_id()); // ctx().set_enode_flag(bv, true); - lp::bound_kind bkind = lp::bound_kind::lower_t; - if (is_strict) bkind = lp::bound_kind::upper_t; - lp::bound* a = alloc(lp::bound, bv, v, is_int, r, bkind); + lp_api::bound_kind bkind = lp_api::bound_kind::lower_t; + if (is_strict) bkind = lp_api::bound_kind::upper_t; + lp_api::bound* a = alloc(lp_api::bound, bv, v, is_int, r, bkind); mk_bound_axioms(*a); updt_unassigned_bounds(v, +1); m_bounds[v].push_back(a); @@ -2622,7 +2622,7 @@ namespace smt { } } - void display_evidence(std::ostream& out, vector> const& evidence) { + void display_evidence(std::ostream& out, vector> const& evidence) { for (auto const& ev : evidence) { expr_ref e(m); SASSERT(!ev.first.is_zero()); diff --git a/src/test/lp/argument_parser.h b/src/test/lp/argument_parser.h index 706167f49..9590baf7b 100644 --- a/src/test/lp/argument_parser.h +++ b/src/test/lp/argument_parser.h @@ -11,7 +11,7 @@ Author: Lev Nachmanson #include #include -namespace lean { +namespace lp { class argument_parser { std::unordered_map m_options; std::unordered_map m_options_with_after_string; diff --git a/src/test/lp/lp.cpp b/src/test/lp/lp.cpp index 71032d013..173bc3b12 100644 --- a/src/test/lp/lp.cpp +++ b/src/test/lp/lp.cpp @@ -31,7 +31,7 @@ Author: Lev Nachmanson #include "util/lp/stacked_unordered_set.h" #include "util/lp/int_set.h" #include "util/stopwatch.h" -namespace lean { +namespace lp { unsigned seed = 1; random_gen g_rand; @@ -78,7 +78,7 @@ void test_matrix(sparse_matrix & a) { a.set(i, j, t); - lean_assert(a.get(i, j) == t); + lp_assert(a.get(i, j) == t); unsigned j1; if (j < m - 1) { @@ -170,7 +170,7 @@ vector allocate_basis_heading(unsigned count) { // the rest of initilizatio void init_basic_part_of_basis_heading(vector & basis, vector & basis_heading) { - lean_assert(basis_heading.size() >= basis.size()); + lp_assert(basis_heading.size() >= basis.size()); unsigned m = basis.size(); for (unsigned i = 0; i < m; i++) { unsigned column = basis[i]; @@ -225,7 +225,7 @@ void test_small_lu(lp_settings & settings) { vector non_basic_columns; init_basis_heading_and_non_basic_columns_vector(basis, heading, non_basic_columns); lu l(m, basis, settings); - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); indexed_vector w(m.row_count()); std::cout << "entering 2, leaving 0" << std::endl; l.prepare_entering(2, w); // to init vector w @@ -235,7 +235,7 @@ void test_small_lu(lp_settings & settings) { // std::cout << "we were factoring " << std::endl; // print_matrix(get_B(l)); // #endif - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); std::cout << "entering 4, leaving 3" << std::endl; l.prepare_entering(4, w); // to init vector w l.replace_column(0, w, heading[3]); @@ -247,7 +247,7 @@ void test_small_lu(lp_settings & settings) { print_matrix(&bl, std::cout); } #endif - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); std::cout << "entering 5, leaving 1" << std::endl; l.prepare_entering(5, w); // to init vector w @@ -260,7 +260,7 @@ void test_small_lu(lp_settings & settings) { print_matrix(&bl, std::cout); } #endif - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); std::cout << "entering 3, leaving 2" << std::endl; l.prepare_entering(3, w); // to init vector w l.replace_column(0, w, heading[2]); @@ -272,7 +272,7 @@ void test_small_lu(lp_settings & settings) { print_matrix(&bl, std::cout); } #endif - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); m.add_row(); m.add_column(); @@ -291,7 +291,7 @@ void test_small_lu(lp_settings & settings) { auto columns_to_replace = l.get_set_of_columns_to_replace_for_add_last_rows(heading); l.add_last_rows_to_B(heading, columns_to_replace); std::cout << "here" << std::endl; - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); } #endif @@ -373,7 +373,7 @@ void test_larger_lu_exp(lp_settings & settings) { dense_matrix left_side = l.get_left_side(basis); dense_matrix right_side = l.get_right_side(); - lean_assert(left_side == right_side); + lp_assert(left_side == right_side); int leaving = 3; int entering = 8; for (unsigned i = 0; i < m.row_count(); i++) { @@ -385,12 +385,12 @@ void test_larger_lu_exp(lp_settings & settings) { l.prepare_entering(entering, w); l.replace_column(0, w, heading[leaving]); change_basis(entering, leaving, basis, non_basic_columns, heading); - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); l.prepare_entering(11, w); // to init vector w l.replace_column(0, w, heading[0]); change_basis(11, 0, basis, non_basic_columns, heading); - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); } void test_larger_lu_with_holes(lp_settings & settings) { @@ -432,7 +432,7 @@ void test_larger_lu_with_holes(lp_settings & settings) { l.prepare_entering(8, w); // to init vector w l.replace_column(0, w, heading[0]); change_basis(8, 0, basis, non_basic_columns, heading); - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); } @@ -479,7 +479,7 @@ void test_larger_lu(lp_settings& settings) { l.prepare_entering(9, w); // to init vector w l.replace_column(0, w, heading[0]); change_basis(9, 0, basis, non_basic_columns, heading); - lean_assert(l.is_correct(basis)); + lp_assert(l.is_correct(basis)); } @@ -612,7 +612,7 @@ void test_swap_rows_with_permutation(sparse_matrix& m){ dense_matrix original(&m); permutation_matrix q(dim); print_matrix(m, std::cout); - lean_assert(original == q * m); + lp_assert(original == q * m); for (int i = 0; i < 100; i++) { unsigned row1 = my_random() % dim; unsigned row2 = my_random() % dim; @@ -620,7 +620,7 @@ void test_swap_rows_with_permutation(sparse_matrix& m){ std::cout << "swap " << row1 << " " << row2 << std::endl; m.swap_rows(row1, row2); q.transpose_from_left(row1, row2); - lean_assert(original == q * m); + lp_assert(original == q * m); print_matrix(m, std::cout); std::cout << std::endl; } @@ -636,7 +636,7 @@ void test_swap_cols_with_permutation(sparse_matrix& m){ dense_matrix original(&m); permutation_matrix q(dim); print_matrix(m, std::cout); - lean_assert(original == q * m); + lp_assert(original == q * m); for (int i = 0; i < 100; i++) { unsigned row1 = my_random() % dim; unsigned row2 = my_random() % dim; @@ -644,7 +644,7 @@ void test_swap_cols_with_permutation(sparse_matrix& m){ std::cout << "swap " << row1 << " " << row2 << std::endl; m.swap_rows(row1, row2); q.transpose_from_right(row1, row2); - lean_assert(original == q * m); + lp_assert(original == q * m); print_matrix(m, std::cout); std::cout << std::endl; } @@ -663,8 +663,8 @@ void test_swap_rows(sparse_matrix& m, unsigned i0, unsigned i1){ m.swap_rows(i0, i1); for (unsigned j = 0; j < m.dimension(); j++) { - lean_assert(mcopy(i0, j) == m(i1, j)); - lean_assert(mcopy(i1, j) == m(i0, j)); + lp_assert(mcopy(i0, j) == m(i1, j)); + lp_assert(mcopy(i1, j) == m(i0, j)); } } template @@ -678,15 +678,15 @@ void test_swap_columns(sparse_matrix& m, unsigned i0, unsigned i1){ m.swap_columns(i0, i1); for (unsigned j = 0; j < m.dimension(); j++) { - lean_assert(mcopy(j, i0) == m(j, i1)); - lean_assert(mcopy(j, i1) == m(j, i0)); + lp_assert(mcopy(j, i0) == m(j, i1)); + lp_assert(mcopy(j, i1) == m(j, i0)); } for (unsigned i = 0; i < m.dimension(); i++) { if (i == i0 || i == i1) continue; for (unsigned j = 0; j < m.dimension(); j++) { - lean_assert(mcopy(j, i)== m(j, i)); + lp_assert(mcopy(j, i)== m(j, i)); } } } @@ -748,7 +748,7 @@ void test_pivot_like_swaps_and_pivot(){ m.pivot_row_to_row(pivot_row_0, beta, target_row, settings); // print_matrix(m); for (unsigned j = 0; j < m.dimension(); j++) { - lean_assert(abs(row[j] - m(target_row, j)) < 0.00000001); + lp_assert(abs(row[j] - m(target_row, j)) < 0.00000001); } } @@ -853,57 +853,57 @@ void sparse_matrix_with_permutaions_test() { m.multiply_from_left(q0); for (unsigned i = 0; i < dim; i++) { for (unsigned j = 0; j < dim; j++) { - lean_assert(m(i, j) == dm0.get_elem(q0[i], j)); + lp_assert(m(i, j) == dm0.get_elem(q0[i], j)); } } auto q0_dm = q0 * dm; - lean_assert(m == q0_dm); + lp_assert(m == q0_dm); m.multiply_from_left(q1); for (unsigned i = 0; i < dim; i++) { for (unsigned j = 0; j < dim; j++) { - lean_assert(m(i, j) == dm0.get_elem(q0[q1[i]], j)); + lp_assert(m(i, j) == dm0.get_elem(q0[q1[i]], j)); } } auto q1_q0_dm = q1 * q0_dm; - lean_assert(m == q1_q0_dm); + lp_assert(m == q1_q0_dm); m.multiply_from_right(p0); for (unsigned i = 0; i < dim; i++) { for (unsigned j = 0; j < dim; j++) { - lean_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p0[j])); + lp_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p0[j])); } } auto q1_q0_dm_p0 = q1_q0_dm * p0; - lean_assert(m == q1_q0_dm_p0); + lp_assert(m == q1_q0_dm_p0); m.multiply_from_right(p1); for (unsigned i = 0; i < dim; i++) { for (unsigned j = 0; j < dim; j++) { - lean_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p1[p0[j]])); + lp_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p1[p0[j]])); } } auto q1_q0_dm_p0_p1 = q1_q0_dm_p0 * p1; - lean_assert(m == q1_q0_dm_p0_p1); + lp_assert(m == q1_q0_dm_p0_p1); m.multiply_from_right(p1); for (unsigned i = 0; i < dim; i++) { for (unsigned j = 0; j < dim; j++) { - lean_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p1[p1[p0[j]]])); + lp_assert(m(i, j) == dm0.get_elem(q0[q1[i]], p1[p1[p0[j]]])); } } auto q1_q0_dm_p0_p1_p1 = q1_q0_dm_p0_p1 * p1; - lean_assert(m == q1_q0_dm_p0_p1_p1); + lp_assert(m == q1_q0_dm_p0_p1_p1); } void test_swap_columns() { @@ -1024,7 +1024,7 @@ void test_apply_reverse_from_right_to_perm(permutation_matrix & #ifdef LEAN_DEBUG auto rev = l.get_inverse(); auto rs = pclone * rev; - lean_assert(p == rs) + lp_assert(p == rs) #endif } @@ -1051,8 +1051,8 @@ void test_permutations() { p.apply_reverse_from_right_to_T(v); p.apply_reverse_from_right_to_T(vi); - lean_assert(vectors_are_equal(v, vi.m_data)); - lean_assert(vi.is_OK()); + lp_assert(vectors_are_equal(v, vi.m_data)); + lp_assert(vi.is_OK()); } void lp_solver_test() { @@ -1200,7 +1200,7 @@ void solve_mps_double(std::string file_name, bool look_for_min, unsigned max_ite compare_solutions(reader, primal_solver, solver); print_x(reader, primal_solver); std::cout << "dual cost is " << cost << ", but primal cost is " << primal_cost << std::endl; - lean_assert(false); + lp_assert(false); } } } @@ -1210,7 +1210,7 @@ void solve_mps_double(std::string file_name, bool look_for_min, unsigned max_ite } void solve_mps_rational(std::string file_name, bool look_for_min, unsigned max_iterations, unsigned time_limit, bool dual, argument_parser & args_parser) { - mps_reader reader(file_name); + mps_reader reader(file_name); reader.read(); if (reader.is_ok()) { auto * solver = reader.create_solver(dual); @@ -1224,7 +1224,7 @@ void solve_mps_rational(std::string file_name, bool look_for_min, unsigned max_i // for (auto name: reader.column_names()) { // std::cout << name << "=" << solver->get_column_value_by_name(name) << ' '; // } - lean::mpq cost = solver->get_current_cost(); + lp::mpq cost = solver->get_current_cost(); if (look_for_min) { cost = -cost; } @@ -1262,7 +1262,7 @@ void solve_mps(std::string file_name, argument_parser & args_parser) { void solve_mps_in_rational(std::string file_name, bool dual, argument_parser & /*args_parser*/) { std::cout << "solving " << file_name << std::endl; - mps_reader reader(file_name); + mps_reader reader(file_name); reader.read(); if (reader.is_ok()) { auto * solver = reader.create_solver(dual); @@ -1274,7 +1274,7 @@ void solve_mps_in_rational(std::string file_name, bool dual, argument_parser & / std::cout << name << "=" << solver->get_column_value_by_name(name).get_double() << ' '; } } - std::cout << std::endl << "cost = " << numeric_traits::get_double(solver->get_current_cost()) << std::endl; + std::cout << std::endl << "cost = " << numeric_traits::get_double(solver->get_current_cost()) << std::endl; } delete solver; } else { @@ -1318,7 +1318,7 @@ void test_binary_priority_queue() { for (unsigned i = 0; i < 10; i++) { unsigned de = q.dequeue(); - lean_assert(i == de); + lp_assert(i == de); std::cout << de << std::endl; } q.enqueue(2, 2); @@ -1341,7 +1341,7 @@ void test_binary_priority_queue() { unsigned t = 0; while (q.size() > 0) { unsigned d =q.dequeue(); - lean_assert(t++ == d); + lp_assert(t++ == d); std::cout << d << std::endl; } #endif @@ -1370,7 +1370,7 @@ void solve_mps_with_known_solution(std::string file_name, std::unordered_mapget_status()) << std::endl; if (status != solver->get_status()){ std::cout << "status should be " << lp_status_to_string(status) << std::endl; - lean_assert(status == solver->get_status()); + lp_assert(status == solver->get_status()); throw "status is wrong"; } if (solver->get_status() == lp_status::OPTIMAL) { @@ -1381,7 +1381,7 @@ void solve_mps_with_known_solution(std::string file_name, std::unordered_mapget_column_value_by_name(it.first) << std::endl; } - lean_assert(fabs(it.second - solver->get_column_value_by_name(it.first)) < 0.000001); + lp_assert(fabs(it.second - solver->get_column_value_by_name(it.first)) < 0.000001); } } if (reader.column_names().size() < 20) { @@ -1466,127 +1466,127 @@ void fill_file_names(vector &file_names, std::set & m return; } std::string home_dir_str(home_dir); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l0redund.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l1.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l2.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l3.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l4.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l4fix.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/plan.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/samp2.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/murtagh.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/l0.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/AFIRO.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SC50B.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SC50A.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/KB2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SC105.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STOCFOR1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/ADLITTLE.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BLEND.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCAGR7.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SC205.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHARE2B.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/RECIPELP.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/LOTFI.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/VTP-BASE.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHARE1B.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BOEING2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BORE3D.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCORPION.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/CAPRI.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BRANDY.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCAGR25.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCTAP1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/ISRAEL.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCFXM1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BANDM.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/E226.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/AGG.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GROW7.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/ETAMACRO.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FINNIS.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCSD1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STANDATA.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STANDGUB.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BEACONFD.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STAIR.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STANDMPS.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GFRD-PNC.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCRS8.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BOEING1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/MODSZK1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/DEGEN2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FORPLAN.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/AGG2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/AGG3.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCFXM2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHELL.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOT4.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCSD6.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP04S.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SEBA.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GROW15.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FFFFF800.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BNL1.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PEROLD.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/QAP8.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCFXM3.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP04L.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GANGES.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCTAP2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GROW22.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP08S.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOT-WE.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/MAROS.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STOCFOR2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/25FV47.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP12S.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCSD8.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FIT1P.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SCTAP3.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SIERRA.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOTNOV.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/CZPROB.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FIT1D.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOT-JA.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP08L.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/BNL2.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/NESM.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/CYCLE.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/acc-tight5.mps"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/SHIP12L.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/DEGEN3.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GREENBEA.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/GREENBEB.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/80BAU3B.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/TRUSS.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/D2Q06C.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/WOODW.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/QAP12.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/D6CUBE.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOT.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/DFL001.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/WOOD1P.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FIT2P.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/PILOT87.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/STOCFOR3.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/QAP15.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/FIT2D.SIF"); - file_names.push_back(home_dir_str + "/projects/lean/src/tests/util/lp/test_files/netlib/MAROS-R7.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/FIT2P.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/DFL001.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/D2Q06C.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/80BAU3B.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/GREENBEB.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/GREENBEA.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/BNL2.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/SHIP08L.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/FIT1D.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/SCTAP3.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/SCSD8.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/SCSD6.SIF"); - minimums.insert("/projects/lean/src/tests/util/lp/test_files/netlib/MAROS-R7.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l0redund.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l1.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l2.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l3.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l4.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l4fix.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/plan.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/samp2.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/murtagh.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/l0.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/AFIRO.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SC50B.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SC50A.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/KB2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SC105.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STOCFOR1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/ADLITTLE.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BLEND.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCAGR7.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SC205.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHARE2B.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/RECIPELP.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/LOTFI.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/VTP-BASE.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHARE1B.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BOEING2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BORE3D.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCORPION.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/CAPRI.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BRANDY.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCAGR25.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCTAP1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/ISRAEL.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCFXM1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BANDM.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/E226.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/AGG.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GROW7.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/ETAMACRO.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FINNIS.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCSD1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STANDATA.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STANDGUB.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BEACONFD.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STAIR.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STANDMPS.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GFRD-PNC.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCRS8.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BOEING1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/MODSZK1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/DEGEN2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FORPLAN.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/AGG2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/AGG3.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCFXM2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHELL.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOT4.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCSD6.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP04S.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SEBA.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GROW15.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FFFFF800.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BNL1.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PEROLD.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/QAP8.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCFXM3.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP04L.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GANGES.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCTAP2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GROW22.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP08S.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOT-WE.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/MAROS.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STOCFOR2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/25FV47.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP12S.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCSD8.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FIT1P.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SCTAP3.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SIERRA.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOTNOV.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/CZPROB.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FIT1D.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOT-JA.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP08L.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/BNL2.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/NESM.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/CYCLE.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/acc-tight5.mps"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/SHIP12L.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/DEGEN3.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GREENBEA.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/GREENBEB.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/80BAU3B.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/TRUSS.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/D2Q06C.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/WOODW.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/QAP12.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/D6CUBE.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOT.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/DFL001.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/WOOD1P.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FIT2P.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/PILOT87.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/STOCFOR3.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/QAP15.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/FIT2D.SIF"); + file_names.push_back(home_dir_str + "/projects/lp/src/tests/util/lp/test_files/netlib/MAROS-R7.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/FIT2P.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/DFL001.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/D2Q06C.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/80BAU3B.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/GREENBEB.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/GREENBEA.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/BNL2.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/SHIP08L.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/FIT1D.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/SCTAP3.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/SCSD8.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/SCSD6.SIF"); + minimums.insert("/projects/lp/src/tests/util/lp/test_files/netlib/MAROS-R7.SIF"); } void test_out_dir(std::string out_dir) { @@ -1706,48 +1706,48 @@ void solve_some_mps(argument_parser & args_parser) { #endif void solve_rational() { - lp_primal_simplex solver; - solver.add_constraint(lp_relation::Equal, lean::mpq(7), 0); - solver.add_constraint(lp_relation::Equal, lean::mpq(-3), 1); + lp_primal_simplex solver; + solver.add_constraint(lp_relation::Equal, lp::mpq(7), 0); + solver.add_constraint(lp_relation::Equal, lp::mpq(-3), 1); // setting the cost int cost[] = {-3, -1, -1, 2, -1, 1, 1, -4}; std::string var_names[8] = {"x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8"}; for (unsigned i = 0; i < 8; i++) { - solver.set_cost_for_column(i, lean::mpq(cost[i])); + solver.set_cost_for_column(i, lp::mpq(cost[i])); solver.give_symbolic_name_to_column(var_names[i], i); } int row0[] = {1, 0, 3, 1, -5, -2 , 4, -6}; for (unsigned i = 0; i < 8; i++) { - solver.set_row_column_coefficient(0, i, lean::mpq(row0[i])); + solver.set_row_column_coefficient(0, i, lp::mpq(row0[i])); } int row1[] = {0, 1, -2, -1, 4, 1, -3, 5}; for (unsigned i = 0; i < 8; i++) { - solver.set_row_column_coefficient(1, i, lean::mpq(row1[i])); + solver.set_row_column_coefficient(1, i, lp::mpq(row1[i])); } int bounds[] = {8, 6, 4, 15, 2, 10, 10, 3}; for (unsigned i = 0; i < 8; i++) { - solver.set_low_bound(i, lean::mpq(0)); - solver.set_upper_bound(i, lean::mpq(bounds[i])); + solver.set_low_bound(i, lp::mpq(0)); + solver.set_upper_bound(i, lp::mpq(bounds[i])); } - std::unordered_map expected_sol; - expected_sol["x1"] = lean::mpq(0); - expected_sol["x2"] = lean::mpq(6); - expected_sol["x3"] = lean::mpq(0); - expected_sol["x4"] = lean::mpq(15); - expected_sol["x5"] = lean::mpq(2); - expected_sol["x6"] = lean::mpq(1); - expected_sol["x7"] = lean::mpq(1); - expected_sol["x8"] = lean::mpq(0); + std::unordered_map expected_sol; + expected_sol["x1"] = lp::mpq(0); + expected_sol["x2"] = lp::mpq(6); + expected_sol["x3"] = lp::mpq(0); + expected_sol["x4"] = lp::mpq(15); + expected_sol["x5"] = lp::mpq(2); + expected_sol["x6"] = lp::mpq(1); + expected_sol["x7"] = lp::mpq(1); + expected_sol["x8"] = lp::mpq(0); solver.find_maximal_solution(); - lean_assert(solver.get_status() == OPTIMAL); + lp_assert(solver.get_status() == OPTIMAL); for (auto it : expected_sol) { - lean_assert(it.second == solver.get_column_value_by_name(it.first)); + lp_assert(it.second == solver.get_column_value_by_name(it.first)); } } @@ -1805,7 +1805,7 @@ std::unordered_map * get_solution_from_glpsol_output(std::s return ret; } - lean_assert(split.size() > 3); + lp_assert(split.size() > 3); (*ret)[split[1]] = atof(split[3].c_str()); } while (true); } @@ -1829,7 +1829,7 @@ void test_init_U() { for (unsigned i = 0; i < 3; i++) { for (unsigned j = 0; j < 3; j ++) { - lean_assert(m(i, basis[j]) == u(i, j)); + lp_assert(m(i, basis[j]) == u(i, j)); } } @@ -1857,7 +1857,7 @@ void test_replace_column() { for (unsigned column_to_replace = 0; column_to_replace < m.dimension(); column_to_replace ++) { m.replace_column(column_to_replace, w, settings); for (unsigned i = 0; i < m.dimension(); i++) { - lean_assert(abs(w[i] - m(i, column_to_replace)) < 0.00000001); + lp_assert(abs(w[i] - m(i, column_to_replace)) < 0.00000001); } } } @@ -1961,7 +1961,7 @@ void test_stacked_unsigned() { v = 3; v = 4; v.pop(); - lean_assert(v == 2); + lp_assert(v == 2); v ++; v++; std::cout << "before push v=" << v << std::endl; @@ -1971,7 +1971,7 @@ void test_stacked_unsigned() { v+=1; std::cout << "v = " << v << std::endl; v.pop(2); - lean_assert(v == 4); + lp_assert(v == 4); const unsigned & rr = v; std::cout << rr << std:: endl; @@ -2020,7 +2020,7 @@ void test_stacked_set() { s.push(); s.insert(4); s.pop(); - lean_assert(s() == scopy); + lp_assert(s() == scopy); s.push(); s.push(); s.insert(4); @@ -2028,7 +2028,7 @@ void test_stacked_set() { s.push(); s.insert(4); s.pop(3); - lean_assert(s() == scopy); + lp_assert(s() == scopy); #endif } @@ -2397,15 +2397,15 @@ void test_files_from_directory(std::string test_file_dir, argument_parser & args } -std::unordered_map get_solution_map(lp_solver * lps, mps_reader & reader) { - std::unordered_map ret; +std::unordered_map get_solution_map(lp_solver * lps, mps_reader & reader) { + std::unordered_map ret; for (auto it : reader.column_names()) { ret[it] = lps->get_column_value_by_name(it); } return ret; } -void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_reader * reader) { +void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_reader * reader) { std::string maxng = args_parser.get_option_value("--maxng"); if (maxng.size() > 0) { solver->settings().max_number_of_iterations_with_no_improvements = atoi(maxng.c_str()); @@ -2425,7 +2425,7 @@ void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_read } auto * lps = reader->create_solver(false); lps->find_maximal_solution(); - std::unordered_map sol = get_solution_map(lps, *reader); + std::unordered_map sol = get_solution_map(lps, *reader); std::cout << "status = " << lp_status_to_string(solver->get_status()) << std::endl; return; } @@ -2434,7 +2434,7 @@ void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_read lp_status status = solver->solve(); std::cout << "status is " << lp_status_to_string(status) << ", processed for " << sw.get_current_seconds() <<" seconds, and " << solver->get_total_iterations() << " iterations" << std::endl; if (solver->get_status() == INFEASIBLE) { - vector> evidence; + vector> evidence; solver->get_infeasibility_explanation(evidence); } if (args_parser.option_is_used("--randomize_lar")) { @@ -2467,7 +2467,7 @@ lar_solver * create_lar_solver_from_file(std::string file_name, argument_parser } return reader.create_lar_solver(); } - mps_reader reader(file_name); + mps_reader reader(file_name); reader.read(); if (!reader.is_ok()) { std::cout << "cannot process " << file_name << std::endl; @@ -2478,8 +2478,8 @@ lar_solver * create_lar_solver_from_file(std::string file_name, argument_parser void test_lar_on_file(std::string file_name, argument_parser & args_parser) { lar_solver * solver = create_lar_solver_from_file(file_name, args_parser); - mps_reader reader(file_name); - mps_reader * mps_reader = nullptr; + mps_reader reader(file_name); + mps_reader * mps_reader = nullptr; reader.read(); if (reader.is_ok()) { mps_reader = & reader; @@ -2524,28 +2524,28 @@ void test_lar_solver(argument_parser & args_parser) { } void test_numeric_pair() { - numeric_pair a; - numeric_pair b(2, lean::mpq(6, 2)); + numeric_pair a; + numeric_pair b(2, lp::mpq(6, 2)); a = b; - numeric_pair c(0.1, 0.5); + numeric_pair c(0.1, 0.5); a += 2*c; a -= c; - lean_assert (a == b + c); - numeric_pair d = a * 2; + lp_assert (a == b + c); + numeric_pair d = a * 2; std::cout << a << std::endl; - lean_assert(b == b); - lean_assert(b < a); - lean_assert(b <= a); - lean_assert(a > b); - lean_assert(a != b); - lean_assert(a >= b); - lean_assert(-a < b); - lean_assert(a < 2 * b); - lean_assert(b + b > a); - lean_assert(lean::mpq(2.1) * b + b > a); - lean_assert(-b * lean::mpq(2.1) - b < lean::mpq(0.99) * a); - std::cout << - b * lean::mpq(2.1) - b << std::endl; - lean_assert(-b *(lean::mpq(2.1) + 1) == - b * lean::mpq(2.1) - b); + lp_assert(b == b); + lp_assert(b < a); + lp_assert(b <= a); + lp_assert(a > b); + lp_assert(a != b); + lp_assert(a >= b); + lp_assert(-a < b); + lp_assert(a < 2 * b); + lp_assert(b + b > a); + lp_assert(lp::mpq(2.1) * b + b > a); + lp_assert(-b * lp::mpq(2.1) - b < lp::mpq(0.99) * a); + std::cout << - b * lp::mpq(2.1) - b << std::endl; + lp_assert(-b *(lp::mpq(2.1) + 1) == - b * lp::mpq(2.1) - b); } void get_matrix_dimensions(std::ifstream & f, unsigned & m, unsigned & n) { @@ -2566,7 +2566,7 @@ void read_row_cols(unsigned i, static_matrix& A, std::ifstream & if (line== "row_end") break; auto r = split_and_trim(line); - lean_assert(r.size() == 4); + lp_assert(r.size() == 4); unsigned j = atoi(r[1].c_str()); double v = atof(r[3].c_str()); A.set(i, j, v); @@ -2594,7 +2594,7 @@ void read_basis(vector & basis, std::ifstream & f) { std::cout << "reading basis" << std::endl; std::string line; getline(f, line); - lean_assert(line == "basis_start"); + lp_assert(line == "basis_start"); do { getline(f, line); if (line == "basis_end") @@ -2607,7 +2607,7 @@ void read_basis(vector & basis, std::ifstream & f) { void read_indexed_vector(indexed_vector & v, std::ifstream & f) { std::string line; getline(f, line); - lean_assert(line == "vector_start"); + lp_assert(line == "vector_start"); do { getline(f, line); if (line == "vector_end") break; @@ -2647,7 +2647,7 @@ void check_lu_from_file(std::string lufile_name) { A.copy_column_to_vector(entering, a); indexed_vector cd(d); B.apply_from_left(cd.m_data, settings); - lean_assert(vectors_are_equal(cd.m_data , a)); + lp_assert(vectors_are_equal(cd.m_data , a)); #endif } @@ -2745,7 +2745,7 @@ void test_evidence_for_total_inf_simple(argument_parser & args_parser) { auto status = solver.solve(); std::cout << lp_status_to_string(status) << std::endl; std::unordered_map model; - lean_assert(solver.get_status() == INFEASIBLE); + lp_assert(solver.get_status() == INFEASIBLE); } void test_bound_propagation_one_small_sample1() { /* @@ -2941,8 +2941,8 @@ void test_total_case_l(){ ls.solve(); bound_propagator bp(ls); ls.propagate_bounds_for_touched_rows(bp); - lean_assert(ev.size() == 4); - lean_assert(contains_j_kind(x, GE, - one_of_type(), ev)); + lp_assert(ev.size() == 4); + lp_assert(contains_j_kind(x, GE, - one_of_type(), ev)); } void test_bound_propagation() { test_total_case_u(); @@ -2962,17 +2962,17 @@ void test_int_set() { s.insert(1); s.insert(2); s.print(std::cout); - lean_assert(s.contains(2)); - lean_assert(s.size() == 2); + lp_assert(s.contains(2)); + lp_assert(s.size() == 2); s.erase(2); - lean_assert(s.size() == 1); + lp_assert(s.size() == 1); s.erase(2); - lean_assert(s.size() == 1); + lp_assert(s.size() == 1); s.print(std::cout); s.insert(3); s.insert(2); s.clear(); - lean_assert(s.size() == 0); + lp_assert(s.size() == 0); } @@ -3226,7 +3226,7 @@ void test_lp_local(int argn, char**argv) { ret = 0; return finalize(ret); } - // lean::ccc = 0; + // lp::ccc = 0; return finalize(0); test_init_U(); test_replace_column(); @@ -3243,5 +3243,5 @@ void test_lp_local(int argn, char**argv) { } } void tst_lp(char ** argv, int argc, int& i) { - lean::test_lp_local(argc - 2, argv + 2); + lp::test_lp_local(argc - 2, argv + 2); } diff --git a/src/test/lp/lp_main.cpp b/src/test/lp/lp_main.cpp index a301f38c6..450664fd0 100644 --- a/src/test/lp/lp_main.cpp +++ b/src/test/lp/lp_main.cpp @@ -2,12 +2,12 @@ void gparams_register_modules(){} void mem_initialize() {} void mem_finalize() {} #include "util/rational.h" -namespace lean { +namespace lp { void test_lp_local(int argc, char**argv); } int main(int argn, char**argv){ rational::initialize(); - lean::test_lp_local(argn, argv); + lp::test_lp_local(argn, argv); rational::finalize(); return 0; } diff --git a/src/test/lp/smt_reader.h b/src/test/lp/smt_reader.h index dd38c6bcd..a2ee0f271 100644 --- a/src/test/lp/smt_reader.h +++ b/src/test/lp/smt_reader.h @@ -23,7 +23,7 @@ #include "util/lp/lar_constraints.h" #include #include -namespace lean { +namespace lp { template T from_string(const std::string& str) { @@ -108,13 +108,13 @@ namespace lean { void fill_simple_elem(lisp_elem & lm) { int separator = first_separator(); - lean_assert(-1 != separator && separator != 0); + lp_assert(-1 != separator && separator != 0); lm.m_head = m_line.substr(0, separator); m_line = m_line.substr(separator); } void fill_nested_elem(lisp_elem & lm) { - lean_assert(m_line[0] == '('); + lp_assert(m_line[0] == '('); m_line = m_line.substr(1); int separator = first_separator(); lm.m_head = m_line.substr(0, separator); @@ -181,11 +181,11 @@ namespace lean { } void adjust_rigth_side(formula_constraint & /* c*/, lisp_elem & /*el*/) { - // lean_assert(el.m_head == "0"); // do nothing for the time being + // lp_assert(el.m_head == "0"); // do nothing for the time being } void set_constraint_coeffs(formula_constraint & c, lisp_elem & el) { - lean_assert(el.m_elems.size() == 2); + lp_assert(el.m_elems.size() == 2); set_constraint_coeffs_on_coeff_element(c, el.m_elems[0]); adjust_rigth_side(c, el.m_elems[1]); } @@ -201,7 +201,7 @@ namespace lean { add_mult_elem(c, el.m_elems); } else if (el.m_head == "~") { lisp_elem & minel = el.m_elems[0]; - lean_assert(minel.is_simple()); + lp_assert(minel.is_simple()); c.m_right_side += mpq(str_to_int(minel.m_head)); } else { std::cout << "unexpected input " << el.m_head << std::endl; @@ -211,14 +211,14 @@ namespace lean { } std::string get_name(lisp_elem & name) { - lean_assert(name.is_simple()); - lean_assert(!is_integer(name.m_head)); + lp_assert(name.is_simple()); + lp_assert(!is_integer(name.m_head)); return name.m_head; } void add_mult_elem(formula_constraint & c, std::vector & els) { - lean_assert(els.size() == 2); + lp_assert(els.size() == 2); mpq coeff = get_coeff(els[0]); std::string col_name = get_name(els[1]); c.add_pair(coeff, col_name); @@ -228,16 +228,16 @@ namespace lean { if (le.is_simple()) { return mpq(str_to_int(le.m_head)); } else { - lean_assert(le.m_head == "~"); - lean_assert(le.size() == 1); + lp_assert(le.m_head == "~"); + lp_assert(le.size() == 1); lisp_elem & el = le.m_elems[0]; - lean_assert(el.is_simple()); + lp_assert(el.is_simple()); return -mpq(str_to_int(el.m_head)); } } int str_to_int(std::string & s) { - lean_assert(is_integer(s)); + lp_assert(is_integer(s)); return atoi(s.c_str()); } @@ -245,7 +245,7 @@ namespace lean { if (el.size()) { add_complex_sum_elem(c, el); } else { - lean_assert(is_integer(el.m_head)); + lp_assert(is_integer(el.m_head)); int v = atoi(el.m_head.c_str()); mpq vr(v); c.m_right_side -= vr; @@ -263,7 +263,7 @@ namespace lean { } else if (el.m_head == "+") { add_sum(c, el.m_elems); } else { - lean_assert(false); // unexpected input + lp_assert(false); // unexpected input } } diff --git a/src/test/lp/test_file_reader.h b/src/test/lp/test_file_reader.h index c7a9e3b8b..5daeb21b6 100644 --- a/src/test/lp/test_file_reader.h +++ b/src/test/lp/test_file_reader.h @@ -15,7 +15,7 @@ Author: Lev Nachmanson #include "util/lp/lp_utils.h" #include "util/lp/lp_solver.h" -namespace lean { +namespace lp { template struct test_result { diff --git a/src/util/lp/binary_heap_priority_queue.h b/src/util/lp/binary_heap_priority_queue.h index a6206948c..04faefd5b 100644 --- a/src/util/lp/binary_heap_priority_queue.h +++ b/src/util/lp/binary_heap_priority_queue.h @@ -7,7 +7,7 @@ #include "util/vector.h" #include "util/debug.h" #include "util/lp/lp_utils.h" -namespace lean { +namespace lp { // the elements with the smallest priority are dequeued first template class binary_heap_priority_queue { @@ -60,7 +60,7 @@ public: /// return the first element of the queue and removes it from the queue unsigned dequeue(); unsigned peek() const { - lean_assert(m_heap_size > 0); + lp_assert(m_heap_size > 0); return m_heap[1]; } #ifdef LEAN_DEBUG diff --git a/src/util/lp/binary_heap_priority_queue.hpp b/src/util/lp/binary_heap_priority_queue.hpp index 440b45b02..d6d9a5358 100644 --- a/src/util/lp/binary_heap_priority_queue.hpp +++ b/src/util/lp/binary_heap_priority_queue.hpp @@ -4,7 +4,7 @@ */ #include "util/vector.h" #include "util/lp/binary_heap_priority_queue.h" -namespace lean { +namespace lp { // is is the child place in heap template void binary_heap_priority_queue::swap_with_parent(unsigned i) { unsigned parent = m_heap[i >> 1]; @@ -33,8 +33,8 @@ template void binary_heap_priority_queue::decrease_priority(unsi template bool binary_heap_priority_queue::is_consistent() const { for (int i = 0; i < m_heap_inverse.size(); i++) { int i_index = m_heap_inverse[i]; - lean_assert(i_index <= static_cast(m_heap_size)); - lean_assert(i_index == -1 || m_heap[i_index] == i); + lp_assert(i_index <= static_cast(m_heap_size)); + lp_assert(i_index == -1 || m_heap[i_index] == i); } for (unsigned i = 1; i < m_heap_size; i++) { unsigned ch = i << 1; @@ -55,7 +55,7 @@ template void binary_heap_priority_queue::remove(unsigned o) { if (o_in_heap == -1) { return; // nothing to do } - lean_assert(static_cast(o_in_heap) <= m_heap_size); + lp_assert(static_cast(o_in_heap) <= m_heap_size); if (static_cast(o_in_heap) < m_heap_size) { put_at(o_in_heap, m_heap[m_heap_size--]); if (m_priorities[m_heap[o_in_heap]] > priority_of_o) { @@ -72,11 +72,11 @@ template void binary_heap_priority_queue::remove(unsigned o) { } } } else { - lean_assert(static_cast(o_in_heap) == m_heap_size); + lp_assert(static_cast(o_in_heap) == m_heap_size); m_heap_size--; } m_heap_inverse[o] = -1; - // lean_assert(is_consistent()); + // lp_assert(is_consistent()); } // n is the initial queue capacity. // The capacity will be enlarged two times automatically if needed @@ -102,7 +102,7 @@ template void binary_heap_priority_queue::put_to_heap(unsigned i template void binary_heap_priority_queue::enqueue_new(unsigned o, const T& priority) { m_heap_size++; int i = m_heap_size; - lean_assert(o < m_priorities.size()); + lp_assert(o < m_priorities.size()); m_priorities[o] = priority; put_at(i, o); while (i > 1 && m_priorities[m_heap[i >> 1]] > priority) { @@ -134,7 +134,7 @@ template void binary_heap_priority_queue::change_priority_for_ex /// return the first element of the queue and removes it from the queue template unsigned binary_heap_priority_queue::dequeue_and_get_priority(T & priority) { - lean_assert(m_heap_size != 0); + lp_assert(m_heap_size != 0); int ret = m_heap[1]; priority = m_priorities[ret]; put_the_last_at_the_top_and_fix_the_heap(); @@ -168,7 +168,7 @@ template void binary_heap_priority_queue::put_the_last_at_the_to } /// return the first element of the queue and removes it from the queue template unsigned binary_heap_priority_queue::dequeue() { - lean_assert(m_heap_size > 0); + lp_assert(m_heap_size > 0); int ret = m_heap[1]; put_the_last_at_the_top_and_fix_the_heap(); m_heap_inverse[ret] = -1; diff --git a/src/util/lp/binary_heap_priority_queue_instances.cpp b/src/util/lp/binary_heap_priority_queue_instances.cpp index 567494d6f..12b853fc8 100644 --- a/src/util/lp/binary_heap_priority_queue_instances.cpp +++ b/src/util/lp/binary_heap_priority_queue_instances.cpp @@ -4,7 +4,7 @@ */ #include "util/lp/numeric_pair.h" #include "util/lp/binary_heap_priority_queue.hpp" -namespace lean { +namespace lp { template binary_heap_priority_queue::binary_heap_priority_queue(unsigned int); template unsigned binary_heap_priority_queue::dequeue(); template void binary_heap_priority_queue::enqueue(unsigned int, int const&); @@ -16,11 +16,11 @@ template unsigned binary_heap_priority_queue::dequeue(); template unsigned binary_heap_priority_queue::dequeue(); template void binary_heap_priority_queue >::enqueue(unsigned int, numeric_pair const&); template void binary_heap_priority_queue >::resize(unsigned int); -template void lean::binary_heap_priority_queue::resize(unsigned int); +template void lp::binary_heap_priority_queue::resize(unsigned int); template binary_heap_priority_queue::binary_heap_priority_queue(unsigned int); template void binary_heap_priority_queue::resize(unsigned int); template unsigned binary_heap_priority_queue::dequeue(); template void binary_heap_priority_queue::enqueue(unsigned int, unsigned int const&); template void binary_heap_priority_queue::remove(unsigned int); -template void lean::binary_heap_priority_queue::resize(unsigned int); +template void lp::binary_heap_priority_queue::resize(unsigned int); } diff --git a/src/util/lp/binary_heap_upair_queue.h b/src/util/lp/binary_heap_upair_queue.h index 26cfd5532..ec7f4e85f 100644 --- a/src/util/lp/binary_heap_upair_queue.h +++ b/src/util/lp/binary_heap_upair_queue.h @@ -15,7 +15,7 @@ typedef std::pair upair; -namespace lean { +namespace lp { template class binary_heap_upair_queue { binary_heap_priority_queue m_q; diff --git a/src/util/lp/binary_heap_upair_queue.hpp b/src/util/lp/binary_heap_upair_queue.hpp index a48bdb5b7..2a162fa06 100644 --- a/src/util/lp/binary_heap_upair_queue.hpp +++ b/src/util/lp/binary_heap_upair_queue.hpp @@ -6,7 +6,7 @@ #include #include "util/lp/lp_utils.h" #include "util/lp/binary_heap_upair_queue.h" -namespace lean { +namespace lp { template binary_heap_upair_queue::binary_heap_upair_queue(unsigned size) : m_q(size), m_pairs(size) { for (unsigned i = 0; i < size; i++) m_available_spots.push_back(i); @@ -14,7 +14,7 @@ template binary_heap_upair_queue::binary_heap_upair_queue(unsign template unsigned binary_heap_upair_queue::dequeue_available_spot() { - lean_assert(m_available_spots.empty() == false); + lp_assert(m_available_spots.empty() == false); unsigned ret = m_available_spots.back(); m_available_spots.pop_back(); return ret; @@ -54,7 +54,7 @@ template void binary_heap_upair_queue::enqueue(unsigned i, unsig m_pairs.resize(new_size); } ij_index = dequeue_available_spot(); - // lean_assert(ij_index void binary_heap_upair_queue::enqueue(unsigned i, unsig } template void binary_heap_upair_queue::dequeue(unsigned & i, unsigned &j) { - lean_assert(!m_q.is_empty()); + lp_assert(!m_q.is_empty()); unsigned ij_index = m_q.dequeue(); upair & p = m_pairs[ij_index]; i = p.first; diff --git a/src/util/lp/binary_heap_upair_queue_instances.cpp b/src/util/lp/binary_heap_upair_queue_instances.cpp index 4c4603110..d315e9bda 100644 --- a/src/util/lp/binary_heap_upair_queue_instances.cpp +++ b/src/util/lp/binary_heap_upair_queue_instances.cpp @@ -3,7 +3,7 @@ Author: Lev Nachmanson */ #include "util/lp/binary_heap_upair_queue.hpp" -namespace lean { +namespace lp { template binary_heap_upair_queue::binary_heap_upair_queue(unsigned int); template binary_heap_upair_queue::binary_heap_upair_queue(unsigned int); template unsigned binary_heap_upair_queue::dequeue_available_spot(); diff --git a/src/util/lp/bound_analyzer_on_row.h b/src/util/lp/bound_analyzer_on_row.h index 508692e5a..45f5288b1 100644 --- a/src/util/lp/bound_analyzer_on_row.h +++ b/src/util/lp/bound_analyzer_on_row.h @@ -13,7 +13,7 @@ // 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 the same loop trying to pin variables by pushing the partial sum up, denoting the variable related to it by _l -namespace lean { +namespace lp { class bound_analyzer_on_row { @@ -91,11 +91,11 @@ public : } const impq & ub(unsigned j) const { - lean_assert(upper_bound_is_available(j)); + lp_assert(upper_bound_is_available(j)); return m_bp.get_upper_bound(j); } const impq & lb(unsigned j) const { - lean_assert(low_bound_is_available(j)); + lp_assert(low_bound_is_available(j)); return m_bp.get_low_bound(j); } @@ -153,7 +153,7 @@ public : void limit_all_monoids_from_above() { int strict = 0; mpq total; - lean_assert(is_zero(total)); + lp_assert(is_zero(total)); m_it.reset(); mpq a; unsigned j; while (m_it.next(a, j)) { @@ -180,7 +180,7 @@ public : void limit_all_monoids_from_below() { int strict = 0; mpq total; - lean_assert(is_zero(total)); + lp_assert(is_zero(total)); m_it.reset(); mpq a; unsigned j; while (m_it.next(a, j)) { @@ -272,7 +272,7 @@ public : // mpq a; unsigned j; // while (it->next(a, j)) { // if (be.m_j == j) continue; - // lean_assert(bound_is_available(j, is_neg(a) ? low_bound : !low_bound)); + // lp_assert(bound_is_available(j, is_neg(a) ? low_bound : !low_bound)); // be.m_vector_of_bound_signatures.emplace_back(a, j, numeric_traits:: // is_neg(a)? low_bound: !low_bound); // } diff --git a/src/util/lp/bound_propagator.cpp b/src/util/lp/bound_propagator.cpp index 0d58ec2be..cfb3aa68f 100644 --- a/src/util/lp/bound_propagator.cpp +++ b/src/util/lp/bound_propagator.cpp @@ -3,7 +3,7 @@ Author: Lev Nachmanson */ #include "util/lp/lar_solver.h" -namespace lean { +namespace lp { bound_propagator::bound_propagator(lar_solver & ls): m_lar_solver(ls) {} column_type bound_propagator::get_column_type(unsigned j) const { diff --git a/src/util/lp/bound_propagator.h b/src/util/lp/bound_propagator.h index 92523d75f..2ef0856fd 100644 --- a/src/util/lp/bound_propagator.h +++ b/src/util/lp/bound_propagator.h @@ -4,7 +4,7 @@ */ #pragma once #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { class lar_solver; class bound_propagator { std::unordered_map m_improved_low_bounds; // these maps map a column index to the corresponding index in ibounds @@ -19,7 +19,7 @@ public: const impq & get_upper_bound(unsigned) const; void try_add_bound(const 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, - lean::lconstraint_kind kind, + 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"; } diff --git a/src/util/lp/breakpoint.h b/src/util/lp/breakpoint.h index e5454db0e..ff3a03e94 100644 --- a/src/util/lp/breakpoint.h +++ b/src/util/lp/breakpoint.h @@ -5,7 +5,7 @@ #pragma once -namespace lean { +namespace lp { enum breakpoint_type { low_break, upper_break, fixed_break }; diff --git a/src/util/lp/column_info.h b/src/util/lp/column_info.h index 56e75a1fb..02c2f638b 100644 --- a/src/util/lp/column_info.h +++ b/src/util/lp/column_info.h @@ -9,7 +9,7 @@ #include #include #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { inline bool is_valid(unsigned j) { return static_cast(j) >= 0;} template @@ -100,11 +100,11 @@ public: } T get_low_bound() const { - lean_assert(m_low_bound_is_set); + lp_assert(m_low_bound_is_set); return m_low_bound; } T get_upper_bound() const { - lean_assert(m_upper_bound_is_set); + lp_assert(m_upper_bound_is_set); return m_upper_bound; } @@ -156,7 +156,7 @@ public: } T get_fixed_value() const { - lean_assert(m_is_fixed); + lp_assert(m_is_fixed); return m_fixed_value; } diff --git a/src/util/lp/column_namer.h b/src/util/lp/column_namer.h index a3fe05dd0..66b6a55db 100644 --- a/src/util/lp/column_namer.h +++ b/src/util/lp/column_namer.h @@ -5,7 +5,7 @@ */ #include #include "util/lp/linear_combination_iterator.h" -namespace lean { +namespace lp { class column_namer { public: virtual std::string get_column_name(unsigned j) const = 0; diff --git a/src/util/lp/conversion_helper.h b/src/util/lp/conversion_helper.h index bff2ad563..cd8577483 100644 --- a/src/util/lp/conversion_helper.h +++ b/src/util/lp/conversion_helper.h @@ -4,7 +4,7 @@ Author: Lev Nachmanson */ #pragma once -namespace lean { +namespace lp { template struct conversion_helper { static V get_low_bound(const column_info & ci) { diff --git a/src/util/lp/core_solver_pretty_printer.h b/src/util/lp/core_solver_pretty_printer.h index 2a3a14b31..cf4caf19d 100644 --- a/src/util/lp/core_solver_pretty_printer.h +++ b/src/util/lp/core_solver_pretty_printer.h @@ -10,7 +10,7 @@ #include #include "util/lp/lp_settings.h" #include "util/lp/indexed_vector.h" -namespace lean { +namespace lp { template class lp_core_solver_base; // forward definition template diff --git a/src/util/lp/core_solver_pretty_printer.hpp b/src/util/lp/core_solver_pretty_printer.hpp index 786b8b3a1..8890f8c20 100644 --- a/src/util/lp/core_solver_pretty_printer.hpp +++ b/src/util/lp/core_solver_pretty_printer.hpp @@ -9,7 +9,7 @@ #include "util/lp/lp_core_solver_base.h" #include "util/lp/core_solver_pretty_printer.h" #include "util/lp/numeric_pair.h" -namespace lean { +namespace lp { template @@ -148,7 +148,7 @@ template void core_solver_pretty_printer::adjust_ case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); break; } } @@ -357,7 +357,7 @@ template void core_solver_pretty_printer::print_g unsigned width = m_column_widths[col]; string s = row[col]; int number_of_blanks = width - static_cast(s.size()); - lean_assert(number_of_blanks >= 0); + lp_assert(number_of_blanks >= 0); print_blanks(number_of_blanks, m_out); m_out << s << ' '; if (col < row.size() - 1) { @@ -368,7 +368,7 @@ template void core_solver_pretty_printer::print_g string rs = T_to_string(rst); int nb = m_rs_width - static_cast(rs.size()); - lean_assert(nb >= 0); + lp_assert(nb >= 0); print_blanks(nb + 1, m_out); m_out << rs << std::endl; } diff --git a/src/util/lp/core_solver_pretty_printer_instances.cpp b/src/util/lp/core_solver_pretty_printer_instances.cpp index cfa72f725..e3801228c 100644 --- a/src/util/lp/core_solver_pretty_printer_instances.cpp +++ b/src/util/lp/core_solver_pretty_printer_instances.cpp @@ -4,12 +4,12 @@ */ #include "util/lp/numeric_pair.h" #include "util/lp/core_solver_pretty_printer.hpp" -template lean::core_solver_pretty_printer::core_solver_pretty_printer(lean::lp_core_solver_base &, std::ostream & out); -template void lean::core_solver_pretty_printer::print(); -template lean::core_solver_pretty_printer::~core_solver_pretty_printer(); -template lean::core_solver_pretty_printer::core_solver_pretty_printer(lean::lp_core_solver_base &, std::ostream & out); -template void lean::core_solver_pretty_printer::print(); -template lean::core_solver_pretty_printer::~core_solver_pretty_printer(); -template lean::core_solver_pretty_printer >::core_solver_pretty_printer(lean::lp_core_solver_base > &, std::ostream & out); -template lean::core_solver_pretty_printer >::~core_solver_pretty_printer(); -template void lean::core_solver_pretty_printer >::print(); +template lp::core_solver_pretty_printer::core_solver_pretty_printer(lp::lp_core_solver_base &, std::ostream & out); +template void lp::core_solver_pretty_printer::print(); +template lp::core_solver_pretty_printer::~core_solver_pretty_printer(); +template lp::core_solver_pretty_printer::core_solver_pretty_printer(lp::lp_core_solver_base &, std::ostream & out); +template void lp::core_solver_pretty_printer::print(); +template lp::core_solver_pretty_printer::~core_solver_pretty_printer(); +template lp::core_solver_pretty_printer >::core_solver_pretty_printer(lp::lp_core_solver_base > &, std::ostream & out); +template lp::core_solver_pretty_printer >::~core_solver_pretty_printer(); +template void lp::core_solver_pretty_printer >::print(); diff --git a/src/util/lp/dense_matrix.h b/src/util/lp/dense_matrix.h index 233f74016..6f2f54338 100644 --- a/src/util/lp/dense_matrix.h +++ b/src/util/lp/dense_matrix.h @@ -6,7 +6,7 @@ #ifdef LEAN_DEBUG #include "util/vector.h" #include "util/lp/matrix.h" -namespace lean { +namespace lp { // used for debugging purposes only template class dense_matrix: public matrix { @@ -31,7 +31,7 @@ public: dense_matrix(unsigned m, unsigned n); dense_matrix operator*=(matrix const & a) { - lean_assert(column_count() == a.row_count()); + lp_assert(column_count() == a.row_count()); dense_matrix c(row_count(), a.column_count()); for (unsigned i = 0; i < row_count(); i++) { for (unsigned j = 0; j < a.column_count(); j++) { diff --git a/src/util/lp/dense_matrix.hpp b/src/util/lp/dense_matrix.hpp index e42d9e3a4..8850d4f74 100644 --- a/src/util/lp/dense_matrix.hpp +++ b/src/util/lp/dense_matrix.hpp @@ -7,7 +7,7 @@ #include "util/vector.h" #include "util/lp/numeric_pair.h" #include "util/lp/dense_matrix.h" -namespace lean { +namespace lp { template void print_vector(const vector & t, std::ostream & out); template dense_matrix::dense_matrix(unsigned m, unsigned n) : m_m(m), m_n(n), m_values(m * n, numeric_traits::zero()) { } @@ -170,7 +170,7 @@ template void dense_matrix::multiply_row_by_const template dense_matrix operator* (matrix & a, matrix & b){ - lean_assert(a.column_count() == b.row_count()); + lp_assert(a.column_count() == b.row_count()); dense_matrix ret(a.row_count(), b.column_count()); for (unsigned i = 0; i < ret.m_m; i++) for (unsigned j = 0; j< ret.m_n; j++) { diff --git a/src/util/lp/dense_matrix_instances.cpp b/src/util/lp/dense_matrix_instances.cpp index 95ba01801..418e2f2e0 100644 --- a/src/util/lp/dense_matrix_instances.cpp +++ b/src/util/lp/dense_matrix_instances.cpp @@ -6,20 +6,20 @@ #include "util/lp/dense_matrix.hpp" #ifdef LEAN_DEBUG #include "util/vector.h" -template lean::dense_matrix lean::operator*(lean::matrix&, lean::matrix&); -template void lean::dense_matrix::apply_from_left(vector &); -template lean::dense_matrix::dense_matrix(lean::matrix const*); -template lean::dense_matrix::dense_matrix(unsigned int, unsigned int); -template lean::dense_matrix& lean::dense_matrix::operator=(lean::dense_matrix const&); -template lean::dense_matrix::dense_matrix(unsigned int, unsigned int); -template lean::dense_matrix >::dense_matrix(lean::matrix > const*); -template void lean::dense_matrix >::apply_from_left(vector&); -template lean::dense_matrix lean::operator*(lean::matrix&, lean::matrix&); -template lean::dense_matrix & lean::dense_matrix::operator=(lean::dense_matrix const&); -template lean::dense_matrix >::dense_matrix(unsigned int, unsigned int); -template lean::dense_matrix >& lean::dense_matrix >::operator=(lean::dense_matrix > const&); -template lean::dense_matrix > lean::operator* >(lean::matrix >&, lean::matrix >&); -template void lean::dense_matrix >::apply_from_right( vector< lean::mpq> &); -template void lean::dense_matrix::apply_from_right(class vector &); -template void lean::dense_matrix::apply_from_left(vector&); +template lp::dense_matrix lp::operator*(lp::matrix&, lp::matrix&); +template void lp::dense_matrix::apply_from_left(vector &); +template lp::dense_matrix::dense_matrix(lp::matrix const*); +template lp::dense_matrix::dense_matrix(unsigned int, unsigned int); +template lp::dense_matrix& lp::dense_matrix::operator=(lp::dense_matrix const&); +template lp::dense_matrix::dense_matrix(unsigned int, unsigned int); +template lp::dense_matrix >::dense_matrix(lp::matrix > const*); +template void lp::dense_matrix >::apply_from_left(vector&); +template lp::dense_matrix lp::operator*(lp::matrix&, lp::matrix&); +template lp::dense_matrix & lp::dense_matrix::operator=(lp::dense_matrix const&); +template lp::dense_matrix >::dense_matrix(unsigned int, unsigned int); +template lp::dense_matrix >& lp::dense_matrix >::operator=(lp::dense_matrix > const&); +template lp::dense_matrix > lp::operator* >(lp::matrix >&, lp::matrix >&); +template void lp::dense_matrix >::apply_from_right( vector< lp::mpq> &); +template void lp::dense_matrix::apply_from_right(class vector &); +template void lp::dense_matrix::apply_from_left(vector&); #endif diff --git a/src/util/lp/eta_matrix.h b/src/util/lp/eta_matrix.h index 51b015066..cfcd11256 100644 --- a/src/util/lp/eta_matrix.h +++ b/src/util/lp/eta_matrix.h @@ -7,7 +7,7 @@ #include "util/vector.h" #include "util/lp/tail_matrix.h" #include "util/lp/permutation_matrix.h" -namespace lean { +namespace lp { // This is the sum of a unit matrix and a one-column matrix template @@ -61,7 +61,7 @@ public: void push_back(unsigned row_index, T val ) { - lean_assert(row_index != m_column_index); + lp_assert(row_index != m_column_index); m_column_vector.push_back(row_index, val); } diff --git a/src/util/lp/eta_matrix.hpp b/src/util/lp/eta_matrix.hpp index 142a408d1..dc1ba9ce5 100644 --- a/src/util/lp/eta_matrix.hpp +++ b/src/util/lp/eta_matrix.hpp @@ -6,7 +6,7 @@ #pragma once #include "util/vector.h" #include "util/lp/eta_matrix.h" -namespace lean { +namespace lp { // This is the sum of a unit matrix and a one-column matrix template @@ -60,7 +60,7 @@ void eta_matrix::apply_from_right(vector & w) { } w[m_column_index] = t; #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(clone_w, w, get_number_of_rows())); + // lp_assert(vectors_are_equal(clone_w, w, get_number_of_rows())); // delete clone_w; #endif } @@ -100,8 +100,8 @@ void eta_matrix::apply_from_right(indexed_vector & w) { } #ifdef LEAN_DEBUG - // lean_assert(w.is_OK()); - // lean_assert(vectors_are_equal(wcopy, w.m_data)); + // lp_assert(w.is_OK()); + // lp_assert(vectors_are_equal(wcopy, w.m_data)); #endif } #ifdef LEAN_DEBUG @@ -130,7 +130,7 @@ void eta_matrix::conjugate_by_permutation(permutation_matrix & p) { pair.first = p.get_rev(pair.first); } #ifdef LEAN_DEBUG - // lean_assert(deb == *this); + // lp_assert(deb == *this); #endif } } diff --git a/src/util/lp/eta_matrix_instances.cpp b/src/util/lp/eta_matrix_instances.cpp index d57d43fed..470a16800 100644 --- a/src/util/lp/eta_matrix_instances.cpp +++ b/src/util/lp/eta_matrix_instances.cpp @@ -7,22 +7,22 @@ #include "util/lp/numeric_pair.h" #include "util/lp/eta_matrix.hpp" #ifdef LEAN_DEBUG -template double lean::eta_matrix::get_elem(unsigned int, unsigned int) const; -template lean::mpq lean::eta_matrix::get_elem(unsigned int, unsigned int) const; -template lean::mpq lean::eta_matrix >::get_elem(unsigned int, unsigned int) const; +template double lp::eta_matrix::get_elem(unsigned int, unsigned int) const; +template lp::mpq lp::eta_matrix::get_elem(unsigned int, unsigned int) const; +template lp::mpq lp::eta_matrix >::get_elem(unsigned int, unsigned int) const; #endif -template void lean::eta_matrix::apply_from_left(vector&, lean::lp_settings&); -template void lean::eta_matrix::apply_from_right(vector&); -template void lean::eta_matrix::conjugate_by_permutation(lean::permutation_matrix&); -template void lean::eta_matrix::apply_from_left(vector&, lean::lp_settings&); -template void lean::eta_matrix::apply_from_right(vector&); -template void lean::eta_matrix::conjugate_by_permutation(lean::permutation_matrix&); -template void lean::eta_matrix >::apply_from_left(vector >&, lean::lp_settings&); -template void lean::eta_matrix >::apply_from_right(vector&); -template void lean::eta_matrix >::conjugate_by_permutation(lean::permutation_matrix >&); -template void lean::eta_matrix::apply_from_left_local(lean::indexed_vector&, lean::lp_settings&); -template void lean::eta_matrix::apply_from_left_local(lean::indexed_vector&, lean::lp_settings&); -template void lean::eta_matrix >::apply_from_left_local(lean::indexed_vector&, lean::lp_settings&); -template void lean::eta_matrix >::apply_from_right(lean::indexed_vector&); -template void lean::eta_matrix::apply_from_right(lean::indexed_vector&); -template void lean::eta_matrix::apply_from_right(lean::indexed_vector&); +template void lp::eta_matrix::apply_from_left(vector&, lp::lp_settings&); +template void lp::eta_matrix::apply_from_right(vector&); +template void lp::eta_matrix::conjugate_by_permutation(lp::permutation_matrix&); +template void lp::eta_matrix::apply_from_left(vector&, lp::lp_settings&); +template void lp::eta_matrix::apply_from_right(vector&); +template void lp::eta_matrix::conjugate_by_permutation(lp::permutation_matrix&); +template void lp::eta_matrix >::apply_from_left(vector >&, lp::lp_settings&); +template void lp::eta_matrix >::apply_from_right(vector&); +template void lp::eta_matrix >::conjugate_by_permutation(lp::permutation_matrix >&); +template void lp::eta_matrix::apply_from_left_local(lp::indexed_vector&, lp::lp_settings&); +template void lp::eta_matrix::apply_from_left_local(lp::indexed_vector&, lp::lp_settings&); +template void lp::eta_matrix >::apply_from_left_local(lp::indexed_vector&, lp::lp_settings&); +template void lp::eta_matrix >::apply_from_right(lp::indexed_vector&); +template void lp::eta_matrix::apply_from_right(lp::indexed_vector&); +template void lp::eta_matrix::apply_from_right(lp::indexed_vector&); diff --git a/src/util/lp/hash_helper.h b/src/util/lp/hash_helper.h index 6fe31d5cd..3d2457a5c 100644 --- a/src/util/lp/hash_helper.h +++ b/src/util/lp/hash_helper.h @@ -12,8 +12,8 @@ #endif namespace std { template<> -struct hash { - inline size_t operator()(const lean::mpq & v) const { +struct hash { + inline size_t operator()(const lp::mpq & v) const { return v.hash(); } }; diff --git a/src/util/lp/implied_bound.h b/src/util/lp/implied_bound.h index 9583e3cd8..45911476f 100644 --- a/src/util/lp/implied_bound.h +++ b/src/util/lp/implied_bound.h @@ -5,7 +5,7 @@ #pragma once #include "util/lp/lp_settings.h" #include "util/lp/lar_constraints.h" -namespace lean { +namespace lp { struct implied_bound { mpq m_bound; unsigned m_j; // the column for which the bound has been found diff --git a/src/util/lp/indexed_value.h b/src/util/lp/indexed_value.h index 7963dfdf9..08a821d10 100644 --- a/src/util/lp/indexed_value.h +++ b/src/util/lp/indexed_value.h @@ -4,7 +4,7 @@ */ #pragma once -namespace lean { +namespace lp { template class indexed_value { public: diff --git a/src/util/lp/indexed_vector.h b/src/util/lp/indexed_vector.h index 4b9a7767d..0e013f778 100644 --- a/src/util/lp/indexed_vector.h +++ b/src/util/lp/indexed_vector.h @@ -11,7 +11,7 @@ #include "util/lp/lp_utils.h" #include "util/lp/lp_settings.h" #include -namespace lean { +namespace lp { template void print_vector(const vector & t, std::ostream & out); template void print_vector(const buffer & t, std::ostream & out); @@ -86,7 +86,7 @@ public: return m_data[i]; } - void clean_up() { + void clp_up() { #if 0==1 for (unsigned k = 0; k < m_index.size(); k++) { unsigned i = m_index[k]; @@ -140,7 +140,7 @@ public: } } - void restore_index_and_clean_from_data() { + void restore_index_and_clp_from_data() { m_index.resize(0); for (unsigned i = 0; i < m_data.size(); i++) { T & v = m_data[i]; diff --git a/src/util/lp/indexed_vector.hpp b/src/util/lp/indexed_vector.hpp index 64e329adc..ff3effeb5 100644 --- a/src/util/lp/indexed_vector.hpp +++ b/src/util/lp/indexed_vector.hpp @@ -5,7 +5,7 @@ #include "util/vector.h" #include "util/lp/indexed_vector.h" #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { template void print_vector(const vector & t, std::ostream & out) { @@ -41,13 +41,13 @@ template void indexed_vector::resize(unsigned data_size) { clear(); m_data.resize(data_size, numeric_traits::zero()); - lean_assert(is_OK()); + lp_assert(is_OK()); } template void indexed_vector::set_value(const T& value, unsigned index) { m_data[index] = value; - lean_assert(std::find(m_index.begin(), m_index.end(), index) == m_index.end()); + lp_assert(std::find(m_index.begin(), m_index.end(), index) == m_index.end()); m_index.push_back(index); } diff --git a/src/util/lp/indexed_vector_instances.cpp b/src/util/lp/indexed_vector_instances.cpp index 6f17a894f..0d6f8c5d2 100644 --- a/src/util/lp/indexed_vector_instances.cpp +++ b/src/util/lp/indexed_vector_instances.cpp @@ -4,7 +4,7 @@ */ #include "util/vector.h" #include "util/lp/indexed_vector.hpp" -namespace lean { +namespace lp { template void indexed_vector::clear(); template void indexed_vector::clear_all(); template void indexed_vector::erase_from_index(unsigned int); @@ -20,17 +20,17 @@ template void indexed_vector::set_value(const unsigned&, unsigned int) #ifdef LEAN_DEBUG template bool indexed_vector::is_OK() const; template bool indexed_vector::is_OK() const; -template bool indexed_vector >::is_OK() const; -template void lean::indexed_vector< lean::mpq>::print(std::basic_ostream > &); -template void lean::indexed_vector::print(std::basic_ostream > &); -template void lean::indexed_vector >::print(std::ostream&); +template bool indexed_vector >::is_OK() const; +template void lp::indexed_vector< lp::mpq>::print(std::basic_ostream > &); +template void lp::indexed_vector::print(std::basic_ostream > &); +template void lp::indexed_vector >::print(std::ostream&); #endif } -template void lean::print_vector(vector const&, std::ostream&); -template void lean::print_vector(vector const&, std::ostream&); -template void lean::print_vector(vector const&, std::ostream&); -template void lean::print_vector >(vector> const&, std::ostream&); -template void lean::indexed_vector::resize(unsigned int); -template void lean::print_vector< lean::mpq>(vector< lean::mpq> const &, std::basic_ostream > &); -template void lean::print_vector >(vector> const&, std::ostream&); -template void lean::indexed_vector >::erase_from_index(unsigned int); +template void lp::print_vector(vector const&, std::ostream&); +template void lp::print_vector(vector const&, std::ostream&); +template void lp::print_vector(vector const&, std::ostream&); +template void lp::print_vector >(vector> const&, std::ostream&); +template void lp::indexed_vector::resize(unsigned int); +template void lp::print_vector< lp::mpq>(vector< lp::mpq> const &, std::basic_ostream > &); +template void lp::print_vector >(vector> const&, std::ostream&); +template void lp::indexed_vector >::erase_from_index(unsigned int); diff --git a/src/util/lp/int_set.h b/src/util/lp/int_set.h index 0619facd8..931125ab5 100644 --- a/src/util/lp/int_set.h +++ b/src/util/lp/int_set.h @@ -6,7 +6,7 @@ #include "util/vector.h" #include "util/lp/indexed_vector.h" #include -namespace lean { +namespace lp { // serves at a set of non-negative integers smaller than the set size class int_set { vector m_data; @@ -20,7 +20,7 @@ public: return m_data[j] >= 0; } void insert(unsigned j) { - lean_assert(j < m_data.size()); + lp_assert(j < m_data.size()); if (contains(j)) return; m_data[j] = m_index.size(); m_index.push_back(j); diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index eb31119b9..f416ad98c 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -5,10 +5,10 @@ #include "util/lp/int_solver.h" #include "util/lp/lar_solver.h" -namespace lean { +namespace lp { void int_solver::fix_non_base_columns() { - lean_assert(is_feasible() && inf_int_set_is_correct()); + lp_assert(is_feasible() && inf_int_set_is_correct()); auto & lcs = m_lar_solver->m_mpq_lar_core_solver; bool change = false; for (unsigned j : lcs.m_r_nbasis) { @@ -22,7 +22,7 @@ void int_solver::fix_non_base_columns() { if (m_lar_solver->find_feasible_solution() == INFEASIBLE) failed(); init_inf_int_set(); - lean_assert(is_feasible() && inf_int_set_is_correct()); + lp_assert(is_feasible() && inf_int_set_is_correct()); } void int_solver::failed() { @@ -30,11 +30,11 @@ void int_solver::failed() { for (unsigned j : m_old_values_set.m_index) { lcs.m_r_x[j] = m_old_values_data[j]; - lean_assert(lcs.m_r_solver.column_is_feasible(j)); + lp_assert(lcs.m_r_solver.column_is_feasible(j)); lcs.m_r_solver.remove_column_from_inf_set(j); } - lean_assert(lcs.m_r_solver.calc_current_x_is_feasible_include_non_basis()); - lean_assert(lcs.m_r_solver.current_x_is_feasible()); + lp_assert(lcs.m_r_solver.calc_current_x_is_feasible_include_non_basis()); + lp_assert(lcs.m_r_solver.current_x_is_feasible()); m_old_values_set.clear(); } @@ -78,7 +78,7 @@ int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { lar_core_solver & lcs = m_lar_solver->m_mpq_lar_core_solver; for (int j : m_inf_int_set.m_index) { - lean_assert(is_base(j) && column_is_int_inf(j)); + lp_assert(is_base(j) && column_is_int_inf(j)); if (!is_boxed(j)) continue; new_range = lcs.m_r_upper_bounds()[j].x - lcs.m_r_low_bounds()[j].x; @@ -109,7 +109,7 @@ int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { } bool int_solver::mk_gomory_cut(unsigned row_index, explanation & ex) { - lean_assert(false); + lp_assert(false); return true; /* const auto & row = m_lar_solver->A_r().m_rows[row_index]; @@ -297,10 +297,10 @@ void int_solver::init_check_data() { } lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { - lean_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); - lean_assert(is_feasible()); + lp_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); + lp_assert(is_feasible()); init_check_data(); - lean_assert(inf_int_set_is_correct()); + lp_assert(inf_int_set_is_correct()); // currently it is a reimplementation of // final_check_status theory_arith::check_int_feasibility() // from theory_arith_int.h @@ -344,7 +344,7 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { if (j != -1) { TRACE("arith_int", tout << "j" << j << " does not have an integer assignment: " << get_value(j) << "\n";); - lean_assert(t.is_empty()); + lp_assert(t.is_empty()); t.add_to_map(j, mpq(1)); k = floor(get_value(j)); TRACE("arith_int", tout << "branching v" << j << " = " << get_value(j) << "\n"; @@ -354,7 +354,7 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { return lia_move::branch; } } - lean_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); + lp_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); // return true; return lia_move::give_up; } @@ -387,7 +387,7 @@ void int_solver::move_non_base_vars_to_bounds() { void int_solver::set_value_for_nbasic_column(unsigned j, const impq & new_val) { - lean_assert(!is_base(j)); + lp_assert(!is_base(j)); auto & x = m_lar_solver->m_mpq_lar_core_solver.m_r_x[j]; if (!m_old_values_set.contains(j)) { m_old_values_set.insert(j); @@ -450,7 +450,7 @@ void int_solver::patch_int_infeasible_columns() { TRACE("patch_int", tout << "patching with 0\n";); } - lean_assert(is_feasible() && inf_int_set_is_correct()); + lp_assert(is_feasible() && inf_int_set_is_correct()); } } @@ -621,7 +621,7 @@ linear_combination_iterator * int_solver::get_column_iterator(unsigned j) { int_solver::int_solver(lar_solver* lar_slv) : m_lar_solver(lar_slv), m_branch_cut_counter(0) { - lean_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_data.resize(lar_slv->A_r().column_count(), zero_of_type()); } @@ -740,8 +740,8 @@ bool int_solver::get_freedom_interval_for_column(unsigned x_j, bool & inf_l, imp tout << "]\n"; tout << "val = " << get_value(x_j) << "\n"; ); - lean_assert(inf_l || l <= get_value(x_j)); - lean_assert(inf_u || u >= get_value(x_j)); + lp_assert(inf_l || l <= get_value(x_j)); + lp_assert(inf_u || u >= get_value(x_j)); return true; } @@ -758,7 +758,7 @@ bool int_solver::value_is_int(unsigned j) const { bool int_solver::is_feasible() const { auto & lcs = m_lar_solver->m_mpq_lar_core_solver; - lean_assert( + lp_assert( lcs.m_r_solver.calc_current_x_is_feasible_include_non_basis() == lcs.m_r_solver.current_x_is_feasible()); return lcs.m_r_solver.current_x_is_feasible(); diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index bac99021b..1d1a1dc69 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -9,7 +9,7 @@ #include "util/lp/int_set.h" #include "util/lp/lar_term.h" -namespace lean { +namespace lp { class lar_solver; template struct lp_constraint; diff --git a/src/util/lp/iterator_on_column.h b/src/util/lp/iterator_on_column.h index 215514b39..a3875deef 100644 --- a/src/util/lp/iterator_on_column.h +++ b/src/util/lp/iterator_on_column.h @@ -6,7 +6,7 @@ #include "util/lp/linear_combination_iterator.h" #include "util/lp/static_matrix.h" #include "util/lp/lar_term.h" -namespace lean { +namespace lp { template struct iterator_on_column:linear_combination_iterator { const vector& m_column; // the offset in term coeffs diff --git a/src/util/lp/iterator_on_indexed_vector.h b/src/util/lp/iterator_on_indexed_vector.h index 532b62617..253661c38 100644 --- a/src/util/lp/iterator_on_indexed_vector.h +++ b/src/util/lp/iterator_on_indexed_vector.h @@ -4,7 +4,7 @@ */ #pragma once #include "util/lp/linear_combination_iterator.h" -namespace lean { +namespace lp { template struct iterator_on_indexed_vector:linear_combination_iterator { const indexed_vector & m_v; diff --git a/src/util/lp/iterator_on_pivot_row.h b/src/util/lp/iterator_on_pivot_row.h index 1a9381a70..cfd0feba4 100644 --- a/src/util/lp/iterator_on_pivot_row.h +++ b/src/util/lp/iterator_on_pivot_row.h @@ -4,7 +4,7 @@ */ #pragma once #include "util/lp/iterator_on_indexed_vector.h" -namespace lean { +namespace lp { template struct iterator_on_pivot_row:linear_combination_iterator { bool m_basis_returned; diff --git a/src/util/lp/iterator_on_row.h b/src/util/lp/iterator_on_row.h index 96a1a8cf3..d5f42340b 100644 --- a/src/util/lp/iterator_on_row.h +++ b/src/util/lp/iterator_on_row.h @@ -4,7 +4,7 @@ */ #pragma once #include "util/lp/linear_combination_iterator.h" -namespace lean { +namespace lp { template struct iterator_on_row:linear_combination_iterator { const vector> & m_row; diff --git a/src/util/lp/iterator_on_term_with_basis_var.h b/src/util/lp/iterator_on_term_with_basis_var.h index 3dd217103..3210b1c27 100644 --- a/src/util/lp/iterator_on_term_with_basis_var.h +++ b/src/util/lp/iterator_on_term_with_basis_var.h @@ -6,7 +6,7 @@ #include "util/lp/linear_combination_iterator.h" #include "util/lp/numeric_pair.h" #include "util/lp/lar_term.h" -namespace lean { +namespace lp { struct iterator_on_term_with_basis_var:linear_combination_iterator { const lar_term & m_term; std::unordered_map::const_iterator m_i; // the offset in term coeffs diff --git a/src/util/lp/lar_constraints.h b/src/util/lp/lar_constraints.h index ee0864a4e..bd11896fb 100644 --- a/src/util/lp/lar_constraints.h +++ b/src/util/lp/lar_constraints.h @@ -12,7 +12,7 @@ #include "util/lp/lp_utils.h" #include "util/lp/ul_pair.h" #include "util/lp/lar_term.h" -namespace lean { +namespace lp { inline lconstraint_kind flip_kind(lconstraint_kind t) { return static_cast( - static_cast(t)); } @@ -25,7 +25,7 @@ inline std::string lconstraint_kind_string(lconstraint_kind t) { case GT: return std::string(">"); case EQ: return std::string("="); } - lean_unreachable(); + lp_unreachable(); return std::string(); // it is unreachable } @@ -74,7 +74,7 @@ public: : lar_base_constraint(kind, right_side), m_coeffs(left_side) {} lar_constraint(const lar_base_constraint & c) { - lean_assert(false); // should not be called : todo! + lp_assert(false); // should not be called : todo! } unsigned size() const { diff --git a/src/util/lp/lar_core_solver.h b/src/util/lp/lar_core_solver.h index 44a6349a7..01afc866c 100644 --- a/src/util/lp/lar_core_solver.h +++ b/src/util/lp/lar_core_solver.h @@ -18,7 +18,7 @@ #include "util/lp/iterator_on_column.h" #include "util/lp/iterator_on_indexed_vector.h" #include "util/lp/stacked_value.h" -namespace lean { +namespace lp { class lar_core_solver { // m_sign_of_entering is set to 1 if the entering variable needs @@ -168,9 +168,9 @@ public: } void push() { - lean_assert(m_r_solver.basis_heading_is_correct()); - lean_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct()); - lean_assert(m_column_types.size() == m_r_A.column_count()); + lp_assert(m_r_solver.basis_heading_is_correct()); + lp_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct()); + lp_assert(m_column_types.size() == m_r_A.column_count()); m_stacked_simplex_strategy = settings().simplex_strategy(); m_stacked_simplex_strategy.push(); m_column_types.push(); @@ -192,7 +192,7 @@ public: template void push_vector(stacked_vector & pushed_vector, const vector & vector) { - lean_assert(pushed_vector.size() <= vector.size()); + lp_assert(pushed_vector.size() <= vector.size()); for (unsigned i = 0; i < vector.size();i++) { if (i == pushed_vector.size()) { pushed_vector.push_back(vector[i]); @@ -242,8 +242,8 @@ public: pop_basis(k); m_stacked_simplex_strategy.pop(k); settings().simplex_strategy() = m_stacked_simplex_strategy; - lean_assert(m_r_solver.basis_heading_is_correct()); - lean_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct()); + lp_assert(m_r_solver.basis_heading_is_correct()); + lp_assert(!need_to_presolve_with_double_solver() || m_d_solver.basis_heading_is_correct()); } bool need_to_presolve_with_double_solver() const { @@ -304,11 +304,11 @@ public: break; default: - lean_assert(false); + lp_assert(false); } break; default: - lean_unreachable(); + lp_unreachable(); } m_r_solver.remove_column_from_inf_set(j); return true; @@ -317,7 +317,7 @@ public: void prepare_solver_x_with_signature_tableau(const lar_solution_signature & signature) { - lean_assert(m_r_solver.inf_set_is_correct()); + lp_assert(m_r_solver.inf_set_is_correct()); for (auto &t : signature) { unsigned j = t.first; if (m_r_heading[j] >= 0) @@ -332,9 +332,9 @@ public: m_r_solver.m_x[jb] -= delta * m_r_solver.m_A.get_val(cc); m_r_solver.update_column_in_inf_set(jb); } - lean_assert(m_r_solver.A_mult_x_is_off() == false); + lp_assert(m_r_solver.A_mult_x_is_off() == false); } - lean_assert(m_r_solver.inf_set_is_correct()); + lp_assert(m_r_solver.inf_set_is_correct()); } @@ -342,7 +342,7 @@ public: void prepare_solver_x_with_signature(const lar_solution_signature & signature, lp_primal_core_solver & s) { for (auto &t : signature) { unsigned j = t.first; - lean_assert(m_r_heading[j] < 0); + lp_assert(m_r_heading[j] < 0); auto pos_type = t.second; switch (pos_type) { case at_low_bound: @@ -359,7 +359,7 @@ public: case not_at_bound: switch (m_column_types[j]) { case column_type::free_column: - lean_assert(false); // unreachable + lp_assert(false); // unreachable case column_type::upper_bound: s.m_x[j] = s.m_upper_bounds[j]; break; @@ -377,15 +377,15 @@ public: s.m_x[j] = s.m_low_bounds[j]; break; default: - lean_assert(false); + lp_assert(false); } break; default: - lean_unreachable(); + lp_unreachable(); } } - lean_assert(is_zero_vector(s.m_b)); + lp_assert(is_zero_vector(s.m_b)); s.solve_Ax_eq_b(); } @@ -418,7 +418,7 @@ public: // the queues of delayed indices std::queue entr_q, leav_q; auto * l = cs.m_factorization; - lean_assert(l->get_status() == LU_status::OK); + lp_assert(l->get_status() == LU_status::OK); for (unsigned i = 0; i < trace_of_basis_change.size(); i+= 2) { unsigned entering = trace_of_basis_change[i]; unsigned leaving = trace_of_basis_change[i+1]; @@ -446,8 +446,8 @@ public: continue; } } - lean_assert(cs.m_basis_heading[entering] < 0); - lean_assert(cs.m_basis_heading[leaving] >= 0); + lp_assert(cs.m_basis_heading[entering] < 0); + lp_assert(cs.m_basis_heading[leaving] >= 0); if (l->get_status() == LU_status::OK) { l->prepare_entering(entering, w); // to init vector w l->replace_column(zero_of_type(), w, cs.m_basis_heading[leaving]); @@ -471,7 +471,7 @@ public: void solve_on_signature_tableau(const lar_solution_signature & signature, const vector & changes_of_basis) { r_basis_is_OK(); - lean_assert(settings().use_tableau()); + lp_assert(settings().use_tableau()); bool r = catch_up_in_lu_tableau(changes_of_basis, m_d_solver.m_basis_heading); if (!r) { // it is the case where m_d_solver gives a degenerated basis @@ -490,10 +490,10 @@ public: return; m_r_solver.stop_tracing_basis_changes(); // and now catch up in the double solver - lean_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2); + lp_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2); catch_up_in_lu(m_r_solver.m_trace_of_basis_change_vector, m_r_solver.m_basis_heading, m_d_solver); } - lean_assert(r_basis_is_OK()); + lp_assert(r_basis_is_OK()); } bool adjust_x_of_column(unsigned j) { @@ -507,16 +507,16 @@ public: } m_r_solver.snap_column_to_bound_tableau(j); - lean_assert(m_r_solver.column_is_feasible(j)); + lp_assert(m_r_solver.column_is_feasible(j)); m_r_solver.m_inf_set.erase(j); */ - lean_assert(false); + lp_assert(false); return true; } bool catch_up_in_lu_tableau(const vector & trace_of_basis_change, const vector & basis_heading) { - lean_assert(r_basis_is_OK()); + lp_assert(r_basis_is_OK()); // the queues of delayed indices std::queue entr_q, leav_q; for (unsigned i = 0; i < trace_of_basis_change.size(); i+= 2) { @@ -546,8 +546,8 @@ public: continue; } } - lean_assert(m_r_solver.m_basis_heading[entering] < 0); - lean_assert(m_r_solver.m_basis_heading[leaving] >= 0); + lp_assert(m_r_solver.m_basis_heading[entering] < 0); + lp_assert(m_r_solver.m_basis_heading[leaving] >= 0); m_r_solver.change_basis_unconditionally(entering, leaving); if(!m_r_solver.pivot_column_tableau(entering, m_r_solver.m_basis_heading[entering])) { // unroll the last step @@ -557,12 +557,12 @@ public: #endif m_r_solver.pivot_column_tableau(leaving, m_r_solver.m_basis_heading[leaving]); #ifdef LEAN_DEBUG - lean_assert(t); + lp_assert(t); #endif return false; } } - lean_assert(r_basis_is_OK()); + lp_assert(r_basis_is_OK()); return true; } @@ -572,21 +572,21 @@ public: if (!m_r_solver.m_settings.use_tableau()) return true; for (unsigned j : m_r_solver.m_basis) { - lean_assert(m_r_solver.m_A.m_columns[j].size() == 1); - lean_assert(m_r_solver.m_A.get_val(m_r_solver.m_A.m_columns[j][0]) == one_of_type()); + lp_assert(m_r_solver.m_A.m_columns[j].size() == 1); + lp_assert(m_r_solver.m_A.get_val(m_r_solver.m_A.m_columns[j][0]) == one_of_type()); } for (unsigned j =0; j < m_r_solver.m_basis_heading.size(); j++) { if (m_r_solver.m_basis_heading[j] >= 0) continue; if (m_r_solver.m_column_types[j] == column_type::fixed) continue; - lean_assert(static_cast(- m_r_solver.m_basis_heading[j] - 1) < m_r_solver.m_column_types.size()); - lean_assert( m_r_solver.m_basis_heading[j] <= -1); + lp_assert(static_cast(- m_r_solver.m_basis_heading[j] - 1) < m_r_solver.m_column_types.size()); + lp_assert( m_r_solver.m_basis_heading[j] <= -1); } #endif return true; } void solve_on_signature(const lar_solution_signature & signature, const vector & changes_of_basis) { - lean_assert(!settings().use_tableau()); + lp_assert(!settings().use_tableau()); if (m_r_solver.m_factorization == nullptr) { for (unsigned j = 0; j < changes_of_basis.size(); j+=2) { unsigned entering = changes_of_basis[j]; @@ -615,7 +615,7 @@ public: return; m_r_solver.stop_tracing_basis_changes(); // and now catch up in the double solver - lean_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2); + lp_assert(m_r_solver.total_iterations() >= m_r_solver.m_trace_of_basis_change_vector.size() /2); catch_up_in_lu(m_r_solver.m_trace_of_basis_change_vector, m_r_solver.m_basis_heading, m_d_solver); } } @@ -641,7 +641,7 @@ public: template void extract_signature_from_lp_core_solver(const lp_primal_core_solver & solver, lar_solution_signature & signature) { signature.clear(); - lean_assert(signature.size() == 0); + lp_assert(signature.size() == 0); for (unsigned j = 0; j < solver.m_basis_heading.size(); j++) { if (solver.m_basis_heading[j] < 0) { signature[j] = solver.get_non_basic_column_value_position(j); @@ -664,7 +664,7 @@ public: if (upper_bound_is_set(j)) { const auto & ub = m_r_solver.m_upper_bounds[j]; m_d_upper_bounds[j] = ub.x.get_double() + delta * ub.y.get_double(); - lean_assert(!low_bound_is_set(j) || (m_d_upper_bounds[j] >= m_d_low_bounds[j])); + lp_assert(!low_bound_is_set(j) || (m_d_upper_bounds[j] >= m_d_low_bounds[j])); } } } @@ -729,7 +729,7 @@ public: case column_type::fixed: return true; default: - lean_assert(false); + lp_assert(false); } return false; } @@ -744,20 +744,20 @@ public: case column_type::fixed: return true; default: - lean_assert(false); + lp_assert(false); } return false; } void update_delta(mpq& delta, numeric_pair const& l, numeric_pair const& u) const { - lean_assert(l <= u); + lp_assert(l <= u); if (l.x < u.x && l.y > u.y) { mpq delta1 = (u.x - l.x) / (l.y - u.y); if (delta1 < delta) { delta = delta1; } } - lean_assert(l.x + delta * l.y <= u.x + delta * u.y); + lp_assert(l.x + delta * l.y <= u.x + delta * u.y); } @@ -804,14 +804,14 @@ public: } const impq & low_bound(unsigned j) const { - lean_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::low_bound); return m_r_low_bounds[j]; } const impq & upper_bound(unsigned j) const { - lean_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::upper_bound); return m_r_upper_bounds[j]; diff --git a/src/util/lp/lar_core_solver.hpp b/src/util/lp/lar_core_solver.hpp index 38c522446..227d2910f 100644 --- a/src/util/lp/lar_core_solver.hpp +++ b/src/util/lp/lar_core_solver.hpp @@ -10,7 +10,7 @@ #include "util/vector.h" #include "util/lp/lar_core_solver.h" #include "util/lp/lar_solution_signature.h" -namespace lean { +namespace lp { lar_core_solver::lar_core_solver( lp_settings & settings, const column_namer & column_names @@ -42,9 +42,9 @@ lar_core_solver::lar_core_solver( column_names){} void lar_core_solver::init_costs(bool first_time) { - lean_assert(false); // should not be called - // lean_assert(this->m_x.size() >= this->m_n()); - // lean_assert(this->m_column_types.size() >= this->m_n()); + lp_assert(false); // should not be called + // lp_assert(this->m_x.size() >= this->m_n()); + // lp_assert(this->m_column_types.size() >= this->m_n()); // if (first_time) // this->m_costs.resize(this->m_n()); // X inf = this->m_infeasibility; @@ -54,7 +54,7 @@ void lar_core_solver::init_costs(bool first_time) { // if (!(first_time || inf >= this->m_infeasibility)) { // LP_OUT(this->m_settings, "iter = " << this->total_iterations() << std::endl); // LP_OUT(this->m_settings, "inf was " << T_to_string(inf) << " and now " << T_to_string(this->m_infeasibility) << std::endl); - // lean_assert(false); + // lp_assert(false); // } // if (inf == this->m_infeasibility) // this->m_iters_with_no_cost_growing++; @@ -105,7 +105,7 @@ void lar_core_solver::init_cost_for_column(unsigned j) { this->m_costs[j] = numeric_traits::zero(); break; default: - lean_assert(false); + lp_assert(false); break; }*/ } @@ -138,7 +138,7 @@ int lar_core_solver::column_is_out_of_bounds(unsigned j) { return 0; break; }*/ - lean_assert(false); + lp_assert(false); return true; } @@ -192,7 +192,7 @@ void lar_core_solver::calculate_pivot_row(unsigned i) { } void lar_core_solver::fill_not_improvable_zero_sum_from_inf_row() { - lean_assert(m_r_solver.A_mult_x_is_off() == false); + lp_assert(m_r_solver.A_mult_x_is_off() == false); unsigned bj = m_r_basis[m_r_solver.m_inf_row_index_for_tableau]; m_infeasible_sum_sign = m_r_solver.inf_sign_of_column(bj); m_infeasible_linear_combination.clear(); @@ -227,15 +227,15 @@ void lar_core_solver::fill_not_improvable_zero_sum() { void lar_core_solver::solve() { - lean_assert(m_r_solver.non_basic_columns_are_set_correctly()); - lean_assert(m_r_solver.inf_set_is_correct()); + lp_assert(m_r_solver.non_basic_columns_are_set_correctly()); + lp_assert(m_r_solver.inf_set_is_correct()); if (m_r_solver.current_x_is_feasible() && m_r_solver.m_look_for_feasible_solution_only) { m_r_solver.set_status(OPTIMAL); return; } ++settings().st().m_need_to_solve_inf; - lean_assert(!m_r_solver.A_mult_x_is_off()); - lean_assert((!settings().use_tableau()) || r_basis_is_OK()); + lp_assert(!m_r_solver.A_mult_x_is_off()); + lp_assert((!settings().use_tableau()) || r_basis_is_OK()); if (need_to_presolve_with_double_solver()) { prefix_d(); lar_solution_signature solution_signature; @@ -248,11 +248,11 @@ void lar_core_solver::solve() { solve_on_signature_tableau(solution_signature, changes_of_basis); else solve_on_signature(solution_signature, changes_of_basis); - lean_assert(!settings().use_tableau() || r_basis_is_OK()); + lp_assert(!settings().use_tableau() || r_basis_is_OK()); } else { if (!settings().use_tableau()) { bool snapped = m_r_solver.snap_non_basic_x_to_bound(); - lean_assert(m_r_solver.non_basic_columns_are_set_correctly()); + lp_assert(m_r_solver.non_basic_columns_are_set_correctly()); if (snapped) m_r_solver.solve_Ax_eq_b(); } @@ -260,16 +260,16 @@ void lar_core_solver::solve() { m_r_solver.find_feasible_solution(); else m_r_solver.solve(); - lean_assert(!settings().use_tableau() || r_basis_is_OK()); + lp_assert(!settings().use_tableau() || r_basis_is_OK()); } if (m_r_solver.get_status() == INFEASIBLE) { fill_not_improvable_zero_sum(); } else if (m_r_solver.get_status() != UNBOUNDED) { m_r_solver.set_status(OPTIMAL); } - lean_assert(r_basis_is_OK()); - lean_assert(m_r_solver.non_basic_columns_are_set_correctly()); - lean_assert(m_r_solver.inf_set_is_correct()); + lp_assert(r_basis_is_OK()); + lp_assert(m_r_solver.non_basic_columns_are_set_correctly()); + lp_assert(m_r_solver.inf_set_is_correct()); } diff --git a/src/util/lp/lar_solution_signature.h b/src/util/lp/lar_solution_signature.h index 2c4169c81..6c8598a73 100644 --- a/src/util/lp/lar_solution_signature.h +++ b/src/util/lp/lar_solution_signature.h @@ -8,6 +8,6 @@ #include "util/debug.h" #include "util/lp/lp_settings.h" #include -namespace lean { +namespace lp { typedef std::unordered_map lar_solution_signature; } diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index eff44d1cd..3e7c994e6 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -4,7 +4,7 @@ Author: Lev Nachmanson */ -namespace lean { +namespace lp { unsigned lar_solver::constraint_count() const { return m_constraints.size(); @@ -23,7 +23,7 @@ lp_settings & lar_solver::settings() { return m_settings;} lp_settings const & lar_solver::settings() const { return m_settings;} -void clear() {lean_assert(false); // not implemented +void clear() {lp_assert(false); // not implemented } @@ -52,7 +52,7 @@ bool lar_solver::is_term(var_index j) const { } unsigned lar_solver::adjust_term_index(unsigned j) const { - lean_assert(is_term(j)); + lp_assert(is_term(j)); return j - m_terms_start_index; } @@ -60,10 +60,10 @@ unsigned lar_solver::adjust_term_index(unsigned j) const { bool lar_solver::use_lu() const { return m_settings.simplex_strategy() == simplex_strategy_enum::lu; } bool lar_solver::sizes_are_correct() const { - lean_assert(strategy_is_undecided() || !m_mpq_lar_core_solver.need_to_presolve_with_double_solver() || A_r().column_count() == A_d().column_count()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_column_types.size()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_x.size()); + lp_assert(strategy_is_undecided() || !m_mpq_lar_core_solver.need_to_presolve_with_double_solver() || A_r().column_count() == A_d().column_count()); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_column_types.size()); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_x.size()); return true; } @@ -105,7 +105,7 @@ bool lar_solver::implied_bound_is_correctly_explained(implied_bound const & be, else if (kind == LE || kind == LT) n_of_L++; rs_of_evidence += coeff*constr.m_right_side; } - lean_assert(n_of_G == 0 || n_of_L == 0); + lp_assert(n_of_G == 0 || n_of_L == 0); lconstraint_kind kind = n_of_G ? GE : (n_of_L ? LE : EQ); if (strict) kind = static_cast((static_cast(kind) / 2)); @@ -149,7 +149,7 @@ bool lar_solver::implied_bound_is_correctly_explained(implied_bound const & be, void lar_solver::analyze_new_bounds_on_row( unsigned row_index, bound_propagator & bp) { - lean_assert(!use_tableau()); + lp_assert(!use_tableau()); iterator_on_pivot_row it(m_mpq_lar_core_solver.get_pivot_row(), m_mpq_lar_core_solver.m_r_basis[row_index]); bound_analyzer_on_row ra_pos(it, @@ -168,7 +168,7 @@ void lar_solver::analyze_new_bounds_on_row_tableau( if (A_r().m_rows[row_index].size() > settings().max_row_length_for_bound_propagation) return; iterator_on_row it(A_r().m_rows[row_index]); - lean_assert(use_tableau()); + lp_assert(use_tableau()); bound_analyzer_on_row::analyze_row(it, zero_of_type>(), row_index, @@ -201,7 +201,7 @@ void lar_solver::calculate_implied_bounds_for_row(unsigned i, bound_propagator & linear_combination_iterator * lar_solver::create_new_iter_from_term(unsigned term_index) const { - lean_assert(false); // not implemented + lp_assert(false); // not implemented return nullptr; // new linear_combination_iterator_on_vector(m_terms[adjust_term_index(term_index)]->coeffs_as_vector()); } @@ -212,7 +212,7 @@ unsigned lar_solver::adjust_column_index_to_term_index(unsigned j) const { } void lar_solver::propagate_bounds_on_a_term(const lar_term& t, bound_propagator & bp, unsigned term_offset) { - lean_assert(false); // not implemented + lp_assert(false); // not implemented } @@ -223,7 +223,7 @@ void lar_solver::explain_implied_bound(implied_bound & ib, bound_propagator & bp unsigned m_j = ib.m_j; if (is_term(m_j)) { auto it = m_ext_vars_to_columns.find(m_j); - lean_assert(it != m_ext_vars_to_columns.end()); + lp_assert(it != m_ext_vars_to_columns.end()); m_j = it->second.ext_j(); } for (auto const& r : A_r().m_rows[i]) { @@ -232,22 +232,22 @@ void lar_solver::explain_implied_bound(implied_bound & ib, bound_propagator & bp if (j == m_j) continue; if (is_term(j)) { auto it = m_ext_vars_to_columns.find(j); - lean_assert(it != m_ext_vars_to_columns.end()); + lp_assert(it != m_ext_vars_to_columns.end()); j = it->second.ext_j(); } int a_sign = is_pos(a)? 1: -1; int sign = j_sign * a_sign; const ul_pair & ul = m_vars_to_ul_pairs[j]; auto witness = sign > 0? ul.upper_bound_witness(): ul.low_bound_witness(); - lean_assert(is_valid(witness)); + lp_assert(is_valid(witness)); bp.consume(a, witness); } - // lean_assert(implied_bound_is_correctly_explained(ib, explanation)); + // lp_assert(implied_bound_is_correctly_explained(ib, explanation)); } bool lar_solver::term_is_used_as_row(unsigned term) const { - lean_assert(is_term(term)); + lp_assert(is_term(term)); return contains(m_ext_vars_to_columns, term); } @@ -338,7 +338,7 @@ void lar_solver::push() { m_constraint_count.push(); } -void lar_solver::clean_large_elements_after_pop(unsigned n, int_set& set) { +void lar_solver::clp_large_elements_after_pop(unsigned n, int_set& set) { vector to_remove; for (unsigned j: set.m_index) if (j >= n) @@ -348,7 +348,7 @@ void lar_solver::clean_large_elements_after_pop(unsigned n, int_set& set) { } void lar_solver::shrink_inf_set_after_pop(unsigned n, int_set & set) { - clean_large_elements_after_pop(n, set); + clp_large_elements_after_pop(n, set); set.resize(n); } @@ -367,16 +367,16 @@ void lar_solver::pop(unsigned k) { m_vars_to_ul_pairs.pop(k); m_mpq_lar_core_solver.pop(k); - clean_large_elements_after_pop(n, m_columns_with_changed_bound); + clp_large_elements_after_pop(n, m_columns_with_changed_bound); unsigned m = A_r().row_count(); - clean_large_elements_after_pop(m, m_rows_with_changed_bounds); - clean_inf_set_of_r_solver_after_pop(); - lean_assert(m_settings.simplex_strategy() == simplex_strategy_enum::undecided || + clp_large_elements_after_pop(m, m_rows_with_changed_bounds); + clp_inf_set_of_r_solver_after_pop(); + lp_assert(m_settings.simplex_strategy() == simplex_strategy_enum::undecided || (!use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); - lean_assert(ax_is_correct()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.inf_set_is_correct()); + lp_assert(ax_is_correct()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.inf_set_is_correct()); m_constraint_count.pop(k); for (unsigned i = m_constraint_count; i < m_constraints.size(); i++) delete m_constraints[i]; @@ -389,8 +389,8 @@ void lar_solver::pop(unsigned k) { m_terms.resize(m_term_count); m_simplex_strategy.pop(k); m_settings.simplex_strategy() = m_simplex_strategy; - lean_assert(sizes_are_correct()); - lean_assert((!m_settings.use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); + lp_assert(sizes_are_correct()); + lp_assert((!m_settings.use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); } vector lar_solver::get_all_constraint_indices() const { @@ -419,13 +419,13 @@ bool lar_solver::maximize_term_on_tableau(const vector bool lar_solver::costs_are_zeros_for_r_solver() const { for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_solver.m_costs.size(); j++) { - lean_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_costs[j])); + lp_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_costs[j])); } return true; } bool lar_solver::reduced_costs_are_zeroes_for_r_solver() const { for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_solver.m_d.size(); j++) { - lean_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_d[j])); + lp_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_d[j])); } return true; } @@ -433,7 +433,7 @@ bool lar_solver::reduced_costs_are_zeroes_for_r_solver() const { void lar_solver::set_costs_to_zero(const vector> & term) { auto & rslv = m_mpq_lar_core_solver.m_r_solver; auto & jset = m_mpq_lar_core_solver.m_r_solver.m_inf_set; // hijack this set that should be empty right now - lean_assert(jset.m_index.size()==0); + lp_assert(jset.m_index.size()==0); for (auto & p : term) { unsigned j = p.second; @@ -452,16 +452,16 @@ void lar_solver::set_costs_to_zero(const vector> & ter jset.clear(); - lean_assert(reduced_costs_are_zeroes_for_r_solver()); - lean_assert(costs_are_zeros_for_r_solver()); + lp_assert(reduced_costs_are_zeroes_for_r_solver()); + lp_assert(costs_are_zeros_for_r_solver()); } void lar_solver::prepare_costs_for_r_solver(const vector> & term) { auto & rslv = m_mpq_lar_core_solver.m_r_solver; rslv.m_using_infeas_costs = false; - lean_assert(costs_are_zeros_for_r_solver()); - lean_assert(reduced_costs_are_zeroes_for_r_solver()); + lp_assert(costs_are_zeros_for_r_solver()); + lp_assert(reduced_costs_are_zeroes_for_r_solver()); rslv.m_costs.resize(A_r().column_count(), zero_of_type()); for (auto & p : term) { unsigned j = p.second; @@ -471,7 +471,7 @@ void lar_solver::prepare_costs_for_r_solver(const vector> & term, @@ -498,10 +498,10 @@ bool lar_solver::maximize_term_on_corrected_r_solver(const vector> & term, impq &term_max) { - lean_assert(m_mpq_lar_core_solver.m_r_solver.current_x_is_feasible()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.current_x_is_feasible()); m_mpq_lar_core_solver.m_r_solver.m_look_for_feasible_solution_only = false; return maximize_term_on_corrected_r_solver(term, term_max); } @@ -517,7 +517,7 @@ bool lar_solver::maximize_term(const vector> & term, const lar_term & lar_solver::get_term(unsigned j) const { - lean_assert(j >= m_terms_start_index); + lp_assert(j >= m_terms_start_index); return *m_terms[j - m_terms_start_index]; } @@ -579,7 +579,7 @@ void lar_solver::detect_rows_of_bound_change_column_for_nbasic_column(unsigned j m_column_buffer.resize(A_r().row_count()); else m_column_buffer.clear(); - lean_assert(m_column_buffer.size() == 0 && m_column_buffer.is_OK()); + lp_assert(m_column_buffer.size() == 0 && m_column_buffer.is_OK()); m_mpq_lar_core_solver.m_r_solver.solve_Bd(j, m_column_buffer); for (unsigned i : m_column_buffer.m_index) @@ -613,7 +613,7 @@ void lar_solver::detect_rows_of_column_with_bound_change(unsigned j) { } void lar_solver::adjust_x_of_column(unsigned j) { - lean_assert(false); + lp_assert(false); } bool lar_solver::row_is_correct(unsigned i) const { @@ -706,14 +706,14 @@ void lar_solver::update_x_and_inf_costs_for_columns_with_changed_bounds() { } void lar_solver::update_x_and_inf_costs_for_columns_with_changed_bounds_tableau() { - lean_assert(ax_is_correct()); + lp_assert(ax_is_correct()); for (auto j : m_columns_with_changed_bound.m_index) update_x_and_inf_costs_for_column_with_changed_bounds(j); if (tableau_with_costs()) { for (unsigned j : m_basic_columns_with_changed_cost.m_index) m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); - lean_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); } } @@ -735,7 +735,7 @@ void lar_solver::solve_with_core_solver() { update_x_and_inf_costs_for_columns_with_changed_bounds(); m_mpq_lar_core_solver.solve(); set_status(m_mpq_lar_core_solver.m_r_solver.get_status()); - lean_assert(m_status != OPTIMAL || all_constraints_hold()); + lp_assert(m_status != OPTIMAL || all_constraints_hold()); } @@ -760,7 +760,7 @@ numeric_pair lar_solver::get_basic_var_value_from_row(unsigned i) { numeric_pair r = zero_of_type>(); m_mpq_lar_core_solver.calculate_pivot_row(i); for (unsigned j : m_mpq_lar_core_solver.m_r_solver.m_pivot_row.m_index) { - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); r -= m_mpq_lar_core_solver.m_r_solver.m_pivot_row.m_data[j] * m_mpq_lar_core_solver.m_r_x[j]; } return r; @@ -824,12 +824,12 @@ unsigned lar_solver::constraint_stack_size() const { } void lar_solver::fill_last_row_of_A_r(static_matrix> & A, const lar_term * ls) { - lean_assert(A.row_count() > 0); - lean_assert(A.column_count() > 0); + lp_assert(A.row_count() > 0); + lp_assert(A.column_count() > 0); unsigned last_row = A.row_count() - 1; - lean_assert(A.m_rows[last_row].size() == 0); + lp_assert(A.m_rows[last_row].size() == 0); for (auto & t : ls->m_coeffs) { - lean_assert(!is_zero(t.second)); + lp_assert(!is_zero(t.second)); var_index j = t.first; A.set(last_row, j, - t.second); } @@ -839,7 +839,7 @@ void lar_solver::fill_last_row_of_A_r(static_matrix> & A, template void lar_solver::create_matrix_A(static_matrix & matr) { - lean_assert(false); // not implemented + lp_assert(false); // not implemented /* unsigned m = number_or_nontrivial_left_sides(); unsigned n = m_vec_of_canonic_left_sides.size(); @@ -920,7 +920,7 @@ bool lar_solver::constraint_holds(const lar_base_constraint & constr, std::unord case GT: return left_side_val > constr.m_right_side; case EQ: return left_side_val == constr.m_right_side; default: - lean_unreachable(); + lp_unreachable(); } return false; // it is unreachable } @@ -965,7 +965,7 @@ bool lar_solver::the_left_sides_sum_to_zero(const vector>& explanation) const { #ifdef LEAN_DEBUG lconstraint_kind kind; - lean_assert(the_relations_are_of_same_type(explanation, kind)); - lean_assert(the_left_sides_sum_to_zero(explanation)); + lp_assert(the_relations_are_of_same_type(explanation, kind)); + lp_assert(the_left_sides_sum_to_zero(explanation)); mpq rs = sum_of_right_sides_of_explanation(explanation); switch (kind) { - case LE: lean_assert(rs < zero_of_type()); + case LE: lp_assert(rs < zero_of_type()); break; - case LT: lean_assert(rs <= zero_of_type()); + case LT: lp_assert(rs <= zero_of_type()); break; - case GE: lean_assert(rs > zero_of_type()); + case GE: lp_assert(rs > zero_of_type()); break; - case GT: lean_assert(rs >= zero_of_type()); + case GT: lp_assert(rs >= zero_of_type()); break; - case EQ: lean_assert(rs != zero_of_type()); + case EQ: lp_assert(rs != zero_of_type()); break; default: - lean_assert(false); + lp_assert(false); return false; } #endif @@ -1034,7 +1034,7 @@ mpq lar_solver::sum_of_right_sides_of_explanation(const vectorm_right_side - m_constraints[con_ind]->get_free_coeff_of_left_side()) * coeff; } return ret; @@ -1091,7 +1091,7 @@ void lar_solver::get_infeasibility_explanation(vector & variable_values) const { mpq delta = mpq(1, 2); // start from 0.5 to have less clashes - lean_assert(m_status == OPTIMAL); + lp_assert(m_status == OPTIMAL); unsigned i; do { @@ -1188,7 +1188,7 @@ mpq lar_solver::get_left_side_val(const lar_base_constraint & cns, const std::u for (auto & it : cns.get_left_side_coefficients()) { var_index j = it.second; auto vi = var_map.find(j); - lean_assert(vi != var_map.end()); + lp_assert(vi != var_map.end()); ret += it.first * vi->second; } return ret; @@ -1234,7 +1234,7 @@ bool lar_solver::column_represents_row_in_tableau(unsigned j) { void lar_solver::make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsigned i, unsigned j) { // i, j - is the indices of the bottom-right element of the tableau - lean_assert(A_r().row_count() == i + 1 && A_r().column_count() == j + 1); + lp_assert(A_r().row_count() == i + 1 && A_r().column_count() == j + 1); auto & last_column = A_r().m_columns[j]; int non_zero_column_cell_index = -1; for (unsigned k = last_column.size(); k-- > 0;){ @@ -1244,13 +1244,13 @@ void lar_solver::make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsign non_zero_column_cell_index = k; } - lean_assert(non_zero_column_cell_index != -1); - lean_assert(static_cast(non_zero_column_cell_index) != i); + lp_assert(non_zero_column_cell_index != -1); + lp_assert(static_cast(non_zero_column_cell_index) != i); m_mpq_lar_core_solver.m_r_solver.transpose_rows_tableau(last_column[non_zero_column_cell_index].m_i, i); } void lar_solver::remove_last_row_and_column_from_tableau(unsigned j) { - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); auto & slv = m_mpq_lar_core_solver.m_r_solver; unsigned i = A_r().row_count() - 1; //last row index make_sure_that_the_bottom_right_elem_not_zero_in_tableau(i, j); @@ -1269,17 +1269,17 @@ void lar_solver::remove_last_row_and_column_from_tableau(unsigned j) { A_r().remove_element(last_row, rc); } - lean_assert(last_row.size() == 0); - lean_assert(A_r().m_columns[j].size() == 0); + lp_assert(last_row.size() == 0); + lp_assert(A_r().m_columns[j].size() == 0); A_r().m_rows.pop_back(); A_r().m_columns.pop_back(); slv.m_b.pop_back(); } void lar_solver::remove_last_column_from_tableau(unsigned j) { - lean_assert(j == A_r().column_count() - 1); + lp_assert(j == A_r().column_count() - 1); // the last column has to be empty - lean_assert(A_r().m_columns[j].size() == 0); + lp_assert(A_r().m_columns[j].size() == 0); A_r().m_columns.pop_back(); } @@ -1288,7 +1288,7 @@ void lar_solver::remove_last_column_from_basis_tableau(unsigned j) { int i = rslv.m_basis_heading[j]; if (i >= 0) { // j is a basic var int last_pos = static_cast(rslv.m_basis.size()) - 1; - lean_assert(last_pos >= 0); + lp_assert(last_pos >= 0); if (i != last_pos) { unsigned j_at_last_pos = rslv.m_basis[last_pos]; rslv.m_basis[i] = j_at_last_pos; @@ -1297,7 +1297,7 @@ void lar_solver::remove_last_column_from_basis_tableau(unsigned j) { rslv.m_basis.pop_back(); // remove j from the basis } else { int last_pos = static_cast(rslv.m_nbasis.size()) - 1; - lean_assert(last_pos >= 0); + lp_assert(last_pos >= 0); i = - 1 - i; if (i != last_pos) { unsigned j_at_last_pos = rslv.m_nbasis[last_pos]; @@ -1307,14 +1307,14 @@ void lar_solver::remove_last_column_from_basis_tableau(unsigned j) { rslv.m_nbasis.pop_back(); // remove j from the basis } rslv.m_basis_heading.pop_back(); - lean_assert(rslv.m_basis.size() == A_r().row_count()); - lean_assert(rslv.basis_heading_is_correct()); + lp_assert(rslv.m_basis.size() == A_r().row_count()); + lp_assert(rslv.basis_heading_is_correct()); } void lar_solver::remove_column_from_tableau(unsigned j) { auto& rslv = m_mpq_lar_core_solver.m_r_solver; - lean_assert(j == A_r().column_count() - 1); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + lp_assert(j == A_r().column_count() - 1); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); if (column_represents_row_in_tableau(j)) { remove_last_row_and_column_from_tableau(j); if (rslv.m_basis_heading[j] < 0) @@ -1328,27 +1328,27 @@ void lar_solver::remove_column_from_tableau(unsigned j) { rslv.m_costs.pop_back(); remove_last_column_from_basis_tableau(j); - lean_assert(m_mpq_lar_core_solver.r_basis_is_OK()); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + lp_assert(m_mpq_lar_core_solver.r_basis_is_OK()); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); } void lar_solver::pop_tableau() { - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); // We remove last variables starting from m_column_names.size() to m_vec_of_canonic_left_sides.size(). // At this moment m_column_names is already popped for (unsigned j = A_r().column_count(); j-- > m_columns_to_ext_vars_or_term_indices.size();) remove_column_from_tableau(j); - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); - lean_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_costs.size() == A_r().column_count()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_basis.size() == A_r().row_count()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); } -void lar_solver::clean_inf_set_of_r_solver_after_pop() { +void lar_solver::clp_inf_set_of_r_solver_after_pop() { vector became_feas; - clean_large_elements_after_pop(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.m_inf_set); + clp_large_elements_after_pop(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.m_inf_set); std::unordered_set basic_columns_with_changed_cost; auto inf_index_copy = m_mpq_lar_core_solver.m_r_solver.m_inf_set.m_index; for (auto j: inf_index_copy) { @@ -1363,14 +1363,14 @@ void lar_solver::clean_inf_set_of_r_solver_after_pop() { } for (unsigned j : became_feas) { - lean_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); + lp_assert(m_mpq_lar_core_solver.m_r_solver.m_basis_heading[j] < 0); m_mpq_lar_core_solver.m_r_solver.m_d[j] -= m_mpq_lar_core_solver.m_r_solver.m_costs[j]; m_mpq_lar_core_solver.m_r_solver.m_costs[j] = zero_of_type(); m_mpq_lar_core_solver.m_r_solver.m_inf_set.erase(j); } became_feas.clear(); for (unsigned j : m_mpq_lar_core_solver.m_r_solver.m_inf_set.m_index) { - lean_assert(m_mpq_lar_core_solver.m_r_heading[j] >= 0); + lp_assert(m_mpq_lar_core_solver.m_r_heading[j] >= 0); if (m_mpq_lar_core_solver.m_r_solver.column_is_feasible(j)) became_feas.push_back(j); } @@ -1383,14 +1383,14 @@ void lar_solver::clean_inf_set_of_r_solver_after_pop() { m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); for (unsigned j : basic_columns_with_changed_cost) m_mpq_lar_core_solver.m_r_solver.update_inf_cost_for_column_tableau(j); - lean_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); + lp_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); } } void lar_solver::shrink_explanation_to_minimum(vector> & explanation) const { // implementing quickXplain quick_xplain::run(explanation, *this); - lean_assert(this->explanation_is_correct(explanation)); + lp_assert(this->explanation_is_correct(explanation)); } bool lar_solver::model_is_int_feasible() const { @@ -1421,7 +1421,7 @@ bool lar_solver::var_is_int(var_index v) const { bool lar_solver::column_is_int(unsigned j) const { unsigned ext_var = m_columns_to_ext_vars_or_term_indices[j]; - lean_assert(contains(m_ext_vars_to_columns, ext_var)); + lp_assert(contains(m_ext_vars_to_columns, ext_var)); return m_ext_vars_to_columns.find(ext_var)->second.is_integer(); } @@ -1432,7 +1432,7 @@ bool lar_solver::column_is_fixed(unsigned j) const { bool lar_solver::ext_var_is_int(var_index ext_var) const { auto it = m_ext_vars_to_columns.find(ext_var); - lean_assert(it != m_ext_vars_to_columns.end()); + lp_assert(it != m_ext_vars_to_columns.end()); return it == m_ext_vars_to_columns.end() || it->second.is_integer(); } @@ -1445,7 +1445,7 @@ bool lar_solver::strategy_is_undecided() const { var_index lar_solver::add_var(unsigned ext_j, bool is_int) { TRACE("add_var", tout << "adding var " << ext_j << (is_int? " int" : " nonint") << std::endl;); var_index i; - lean_assert(ext_j < m_terms_start_index); + lp_assert(ext_j < m_terms_start_index); if (ext_j >= m_terms_start_index) throw 0; // todo : what is the right way to exit? @@ -1453,19 +1453,19 @@ var_index lar_solver::add_var(unsigned ext_j, bool is_int) { if (it != m_ext_vars_to_columns.end()) { return it->second.ext_j(); } - lean_assert(m_vars_to_ul_pairs.size() == A_r().column_count()); + lp_assert(m_vars_to_ul_pairs.size() == A_r().column_count()); i = A_r().column_count(); m_vars_to_ul_pairs.push_back(ul_pair(static_cast(-1))); add_non_basic_var_to_core_fields(ext_j, is_int); - lean_assert(sizes_are_correct()); + lp_assert(sizes_are_correct()); return i; } void lar_solver::register_new_ext_var_index(unsigned ext_v, bool is_int) { - lean_assert(!contains(m_ext_vars_to_columns, ext_v)); + lp_assert(!contains(m_ext_vars_to_columns, ext_v)); unsigned j = static_cast(m_ext_vars_to_columns.size()); m_ext_vars_to_columns.insert(std::make_pair(ext_v, ext_var_info(j, is_int))); - lean_assert(m_columns_to_ext_vars_or_term_indices.size() == j); + lp_assert(m_columns_to_ext_vars_or_term_indices.size() == j); m_columns_to_ext_vars_or_term_indices.push_back(ext_v); } @@ -1481,12 +1481,12 @@ void lar_solver::add_non_basic_var_to_core_fields(unsigned ext_j, bool is_int) { void lar_solver::add_new_var_to_core_fields_for_doubles(bool register_in_basis) { unsigned j = A_d().column_count(); A_d().add_column(); - lean_assert(m_mpq_lar_core_solver.m_d_x.size() == j); - // lean_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_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 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_upper_bounds.resize(j + 1); - lean_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) { A_d().add_row(); m_mpq_lar_core_solver.m_d_heading.push_back(m_mpq_lar_core_solver.m_d_basis.size()); @@ -1501,15 +1501,15 @@ void lar_solver::add_new_var_to_core_fields_for_doubles(bool register_in_basis) void lar_solver::add_new_var_to_core_fields_for_mpq(bool register_in_basis) { unsigned j = A_r().column_count(); A_r().add_column(); - lean_assert(m_mpq_lar_core_solver.m_r_x.size() == j); - // lean_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_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 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_upper_bounds.increase_size_by_one(); m_mpq_lar_core_solver.m_r_solver.m_inf_set.increase_size_by_one(); m_mpq_lar_core_solver.m_r_solver.m_costs.resize(j + 1); m_mpq_lar_core_solver.m_r_solver.m_d.resize(j + 1); - lean_assert(m_mpq_lar_core_solver.m_r_heading.size() == j); // as A().column_count() on the entry to the method + lp_assert(m_mpq_lar_core_solver.m_r_heading.size() == j); // as A().column_count() on the entry to the method if (register_in_basis) { A_r().add_row(); m_mpq_lar_core_solver.m_r_heading.push_back(m_mpq_lar_core_solver.m_r_basis.size()); @@ -1544,14 +1544,14 @@ var_index lar_solver::add_term(const vector> & coeffs, if (m_settings.bound_propagation()) m_rows_with_changed_bounds.insert(A_r().row_count() - 1); } - lean_assert(m_ext_vars_to_columns.size() == A_r().column_count()); + lp_assert(m_ext_vars_to_columns.size() == A_r().column_count()); return ret; } void lar_solver::add_row_for_term(const lar_term * term, unsigned term_ext_index) { - lean_assert(sizes_are_correct()); + lp_assert(sizes_are_correct()); add_row_from_term_no_constraint(term, term_ext_index); - lean_assert(sizes_are_correct()); + lp_assert(sizes_are_correct()); } void lar_solver::add_row_from_term_no_constraint(const lar_term * term, unsigned term_ext_index) { @@ -1577,7 +1577,7 @@ void lar_solver::add_row_from_term_no_constraint(const lar_term * term, unsigned void lar_solver::add_basic_var_to_core_fields() { bool use_lu = m_mpq_lar_core_solver.need_to_presolve_with_double_solver(); - lean_assert(!use_lu || A_r().column_count() == A_d().column_count()); + lp_assert(!use_lu || A_r().column_count() == A_d().column_count()); m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column); m_columns_with_changed_bound.increase_size_by_one(); m_rows_with_changed_bounds.increase_size_by_one(); @@ -1595,7 +1595,7 @@ bool lar_solver::bound_is_integer_if_needed(unsigned j, const mpq & right_side) constraint_index lar_solver::add_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side) { constraint_index ci = m_constraints.size(); if (!is_term(j)) { // j is a var - lean_assert(bound_is_integer_if_needed(j, right_side)); + lp_assert(bound_is_integer_if_needed(j, right_side)); auto vc = new lar_var_constraint(j, kind, right_side); m_constraints.push_back(vc); update_column_type_and_bound(j, kind, right_side, ci); @@ -1603,7 +1603,7 @@ constraint_index lar_solver::add_var_bound(var_index j, lconstraint_kind kind, c else { add_var_bound_on_constraint_for_term(j, kind, right_side, ci); } - lean_assert(sizes_are_correct()); + lp_assert(sizes_are_correct()); return ci; } @@ -1625,14 +1625,14 @@ void lar_solver::update_column_type_and_bound(var_index j, lconstraint_kind kind update_fixed_column_type_and_bound(j, kind, right_side, constr_index); break; default: - lean_assert(false); // cannot be here + lp_assert(false); // cannot be here } } void lar_solver::add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lean_assert(is_term(j)); + lp_assert(is_term(j)); unsigned adjusted_term_index = adjust_term_index(j); - lean_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); if (it != m_ext_vars_to_columns.end()) { unsigned term_j = it->second.ext_j(); @@ -1662,11 +1662,11 @@ void lar_solver::add_constraint_from_term_and_create_new_column_row(unsigned ter unsigned j = A_r().column_count() - 1; update_column_type_and_bound(j, kind, right_side - term->m_v, m_constraints.size()); m_constraints.push_back(new lar_term_constraint(term, kind, right_side)); - lean_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); + lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); } void lar_solver::decide_on_strategy_and_adjust_initial_state() { - lean_assert(strategy_is_undecided()); + lp_assert(strategy_is_undecided()); if (m_vars_to_ul_pairs.size() > m_settings.column_number_threshold_for_using_lu_in_lar_solver) { m_settings.simplex_strategy() = simplex_strategy_enum::lu; } @@ -1685,7 +1685,7 @@ void lar_solver::adjust_initial_state() { adjust_initial_state_for_tableau_rows(); break; case simplex_strategy_enum::tableau_costs: - lean_assert(false); // not implemented + lp_assert(false); // not implemented case simplex_strategy_enum::undecided: adjust_initial_state_for_tableau_rows(); break; @@ -1704,12 +1704,12 @@ void lar_solver::adjust_initial_state_for_lu() { /* unsigned j = A_d().column_count(); A_d().add_column(); - lean_assert(m_mpq_lar_core_solver.m_d_x.size() == j); - // lean_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_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 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_upper_bounds.resize(j + 1); - lean_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) { A_d().add_row(); m_mpq_lar_core_solver.m_d_heading.push_back(m_mpq_lar_core_solver.m_d_basis.size()); @@ -1730,13 +1730,13 @@ void lar_solver::adjust_initial_state_for_tableau_rows() { // this fills the last row of A_d and sets the basis column: -1 in the last column of the row void lar_solver::fill_last_row_of_A_d(static_matrix & A, const lar_term* ls) { - lean_assert(A.row_count() > 0); - lean_assert(A.column_count() > 0); + lp_assert(A.row_count() > 0); + lp_assert(A.column_count() > 0); unsigned last_row = A.row_count() - 1; - lean_assert(A.m_rows[last_row].empty()); + lp_assert(A.m_rows[last_row].empty()); for (auto & t : ls->m_coeffs) { - lean_assert(!is_zero(t.second)); + lp_assert(!is_zero(t.second)); var_index j = t.first; A.set(last_row, j, -t.second.get_double()); } @@ -1752,8 +1752,8 @@ void lar_solver::update_free_column_type_and_bound(var_index j, lconstraint_kind y_of_bound = -1; case LE: m_mpq_lar_core_solver.m_column_types[j] = column_type::upper_bound; - lean_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound); - lean_assert(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j); + lp_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound); + lp_assert(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j); { auto up = numeric_pair(right_side, y_of_bound); m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; @@ -1764,7 +1764,7 @@ void lar_solver::update_free_column_type_and_bound(var_index j, lconstraint_kind y_of_bound = 1; case GE: m_mpq_lar_core_solver.m_column_types[j] = column_type::low_bound; - lean_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(right_side, y_of_bound); m_mpq_lar_core_solver.m_r_low_bounds[j] = low; @@ -1779,14 +1779,14 @@ void lar_solver::update_free_column_type_and_bound(var_index j, lconstraint_kind break; default: - lean_unreachable(); + lp_unreachable(); } m_columns_with_changed_bound.insert(j); } void lar_solver::update_upper_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lean_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound); + lp_assert(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound); mpq y_of_bound(0); switch (kind) { case LT: @@ -1839,13 +1839,13 @@ void lar_solver::update_upper_bound_column_type_and_bound(var_index j, lconstrai break; default: - lean_unreachable(); + lp_unreachable(); } } void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lean_assert(m_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 == 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])); mpq y_of_bound(0); switch (kind) { case LT: @@ -1861,7 +1861,7 @@ void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kin if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) { m_status = INFEASIBLE; - lean_assert(false); + lp_assert(false); m_infeasible_column_index = j; } else { @@ -1914,12 +1914,12 @@ void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kin } default: - lean_unreachable(); + lp_unreachable(); } } void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lean_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::low_bound); mpq y_of_bound(0); switch (kind) { case LT: @@ -1971,14 +1971,14 @@ void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint } default: - lean_unreachable(); + lp_unreachable(); } } void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lean_assert(m_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])); - lean_assert(m_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 == 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 == 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())); auto v = numeric_pair(right_side, mpq(0)); mpq y_of_bound(0); @@ -2033,12 +2033,12 @@ void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kin } default: - lean_unreachable(); + lp_unreachable(); } } -} // namespace lean +} // namespace lp diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index dbccbc9cf..0961d2b8d 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -33,7 +33,7 @@ #include "util/lp/int_solver.h" #include "util/lp/nra_solver.h" -namespace lean { +namespace lp { class lar_solver : public column_namer { @@ -222,7 +222,7 @@ public: vector get_list_of_all_var_indices() const; void push(); - static void clean_large_elements_after_pop(unsigned n, int_set& set); + static void clp_large_elements_after_pop(unsigned n, int_set& set); static void shrink_inf_set_after_pop(unsigned n, int_set & set); @@ -403,7 +403,7 @@ public: void remove_last_column_from_basis_tableau(unsigned j); void remove_column_from_tableau(unsigned j); void pop_tableau(); - void clean_inf_set_of_r_solver_after_pop(); + void clp_inf_set_of_r_solver_after_pop(); void shrink_explanation_to_minimum(vector> & explanation) const; diff --git a/src/util/lp/lar_solver_instances.cpp b/src/util/lp/lar_solver_instances.cpp index 98f59edb9..602df0326 100644 --- a/src/util/lp/lar_solver_instances.cpp +++ b/src/util/lp/lar_solver_instances.cpp @@ -5,7 +5,7 @@ #include "util/lp/lar_solver.cpp" -template void lean::lar_solver::copy_from_mpq_matrix(class lean::static_matrix &); +template void lp::lar_solver::copy_from_mpq_matrix(class lp::static_matrix &); diff --git a/src/util/lp/lar_term.h b/src/util/lp/lar_term.h index dfdedb571..71320b7c3 100644 --- a/src/util/lp/lar_term.h +++ b/src/util/lp/lar_term.h @@ -4,7 +4,7 @@ */ #pragma once #include "util/lp/indexed_vector.h" -namespace lean { +namespace lp { struct lar_term { // the term evaluates to sum of m_coeffs + m_v std::unordered_map m_coeffs; diff --git a/src/util/lp/linear_combination_iterator.h b/src/util/lp/linear_combination_iterator.h index 634accfd4..d8a67f1b8 100644 --- a/src/util/lp/linear_combination_iterator.h +++ b/src/util/lp/linear_combination_iterator.h @@ -3,7 +3,7 @@ Author: Lev Nachmanson */ #pragma once -namespace lean { +namespace lp { template struct linear_combination_iterator { virtual bool next(T & a, unsigned & i) = 0; diff --git a/src/util/lp/lp_core_solver_base.h b/src/util/lp/lp_core_solver_base.h index 7599a9d2d..28cb14011 100644 --- a/src/util/lp/lp_core_solver_base.h +++ b/src/util/lp/lp_core_solver_base.h @@ -16,7 +16,7 @@ #include "util/lp/iterator_on_row.h" #include "util/lp/iterator_on_pivot_row.h" -namespace lean { +namespace lp { template // X represents the type of the x variable and the bounds class lp_core_solver_base { @@ -185,11 +185,11 @@ public: bool need_to_pivot_to_basis_tableau() const { - lean_assert(m_A.is_correct()); + lp_assert(m_A.is_correct()); unsigned m = m_A.row_count(); for (unsigned i = 0; i < m; i++) { unsigned bj = m_basis[i]; - lean_assert(m_A.m_columns[bj].size() > 0); + lp_assert(m_A.m_columns[bj].size() > 0); if (m_A.m_columns[bj].size() > 1 || m_A.get_val(m_A.m_columns[bj][0]) != one_of_type()) return true; } return false; @@ -198,7 +198,7 @@ public: bool reduced_costs_are_correct_tableau() const { if (m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows) return true; - lean_assert(m_A.is_correct()); + lp_assert(m_A.is_correct()); if (m_using_infeas_costs) { if (infeasibility_costs_are_correct() == false) { std::cout << "infeasibility_costs_are_correct() does not hold" << std::endl; @@ -373,11 +373,11 @@ public: } bool make_column_feasible(unsigned j, numeric_pair & delta) { - lean_assert(m_basis_heading[j] < 0); + lp_assert(m_basis_heading[j] < 0); auto & x = m_x[j]; switch (m_column_types[j]) { case column_type::fixed: - lean_assert(m_low_bounds[j] == m_upper_bounds[j]); + lp_assert(m_low_bounds[j] == m_upper_bounds[j]); if (x != m_low_bounds[j]) { delta = m_low_bounds[j] - x; x = m_low_bounds[j]; @@ -413,7 +413,7 @@ public: case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); break; } return false; @@ -462,7 +462,7 @@ public: } void change_basis_unconditionally(unsigned entering, unsigned leaving) { - lean_assert(m_basis_heading[entering] < 0); + lp_assert(m_basis_heading[entering] < 0); int place_in_non_basis = -1 - m_basis_heading[entering]; if (static_cast(place_in_non_basis) >= m_nbasis.size()) { // entering variable in not in m_nbasis, we need to put it back; @@ -481,8 +481,8 @@ public: } void change_basis(unsigned entering, unsigned leaving) { - lean_assert(m_basis_heading[entering] < 0); - lean_assert(m_basis_heading[leaving] >= 0); + lp_assert(m_basis_heading[entering] < 0); + lp_assert(m_basis_heading[leaving] >= 0); int place_in_basis = m_basis_heading[leaving]; int place_in_non_basis = - m_basis_heading[entering] - 1; @@ -523,7 +523,7 @@ public: case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); break; } return true; @@ -571,7 +571,7 @@ public: case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); } out << "basis heading = " << m_basis_heading[j] << std::endl; out << "x = " << m_x[j] << std::endl; @@ -670,17 +670,17 @@ public: } void insert_column_into_inf_set(unsigned j) { m_inf_set.insert(j); - lean_assert(!column_is_feasible(j)); + lp_assert(!column_is_feasible(j)); } void remove_column_from_inf_set(unsigned j) { m_inf_set.erase(j); - lean_assert(column_is_feasible(j)); + lp_assert(column_is_feasible(j)); } bool costs_on_nbasis_are_zeros() const { - lean_assert(this->basis_heading_is_correct()); + lp_assert(this->basis_heading_is_correct()); for (unsigned j = 0; j < this->m_n(); j++) { if (this->m_basis_heading[j] < 0) - lean_assert(is_zero(this->m_costs[j])); + lp_assert(is_zero(this->m_costs[j])); } return true; } diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp index 48494d207..26d6f49c7 100644 --- a/src/util/lp/lp_core_solver_base.hpp +++ b/src/util/lp/lp_core_solver_base.hpp @@ -7,7 +7,7 @@ #include "util/vector.h" #include "util/lp/lp_utils.h" #include "util/lp/lp_core_solver_base.h" -namespace lean { +namespace lp { template lp_core_solver_base:: lp_core_solver_base(static_matrix & A, @@ -53,7 +53,7 @@ lp_core_solver_base(static_matrix & A, m_tracing_basis_changes(false), m_pivoted_rows(nullptr), m_look_for_feasible_solution_only(false) { - lean_assert(bounds_for_boxed_are_set_correctly()); + lp_assert(bounds_for_boxed_are_set_correctly()); init(); init_basis_heading_and_non_basic_columns_vector(); } @@ -61,7 +61,7 @@ lp_core_solver_base(static_matrix & A, template void lp_core_solver_base:: allocate_basis_heading() { // the rest of initilization will be handled by the factorization class init_basis_heading_and_non_basic_columns_vector(); - lean_assert(basis_heading_is_correct()); + lp_assert(basis_heading_is_correct()); } template void lp_core_solver_base:: init() { @@ -127,7 +127,7 @@ solve_yB(vector & y) { // } // } template void lp_core_solver_base::solve_Bd(unsigned entering, indexed_vector & column) { - lean_assert(!m_settings.use_tableau()); + lp_assert(!m_settings.use_tableau()); if (m_factorization == nullptr) { init_factorization(m_factorization, m_A, m_basis, m_settings); } @@ -137,19 +137,19 @@ template void lp_core_solver_base::solve_Bd(unsig template void lp_core_solver_base:: solve_Bd(unsigned entering) { - lean_assert(m_ed.is_OK()); + lp_assert(m_ed.is_OK()); m_factorization->solve_Bd(entering, m_ed, m_w); if (this->precise()) m_columns_nz[entering] = m_ed.m_index.size(); - lean_assert(m_ed.is_OK()); - lean_assert(m_w.is_OK()); + lp_assert(m_ed.is_OK()); + lp_assert(m_w.is_OK()); #ifdef LEAN_DEBUG // auto B = get_B(*m_factorization, m_basis); // vector a(m_m()); // m_A.copy_column_to_vector(entering, a); // vector cd(m_ed.m_data); // B.apply_from_left(cd, m_settings); - // lean_assert(vectors_are_equal(cd , a)); + // lp_assert(vectors_are_equal(cd , a)); #endif } @@ -208,7 +208,7 @@ restore_m_ed(T * buffer) { template bool lp_core_solver_base:: A_mult_x_is_off() const { - lean_assert(m_x.size() == m_A.column_count()); + lp_assert(m_x.size() == m_A.column_count()); if (numeric_traits::precise()) { for (unsigned i = 0; i < m_m(); i++) { X delta = m_b[i] - m_A.dot_product_with_row(i, m_x); @@ -244,7 +244,7 @@ A_mult_x_is_off() const { } template bool lp_core_solver_base:: A_mult_x_is_off_on_index(const vector & index) const { - lean_assert(m_x.size() == m_A.column_count()); + lp_assert(m_x.size() == m_A.column_count()); if (numeric_traits::precise()) return false; #if RUN_A_MULT_X_IS_OFF_FOR_PRECESE for (unsigned i : index) { @@ -284,13 +284,13 @@ A_mult_x_is_off_on_index(const vector & index) const { // from page 182 of Istvan Maros's book template void lp_core_solver_base:: calculate_pivot_row_of_B_1(unsigned pivot_row) { - lean_assert(! use_tableau()); - lean_assert(m_pivot_row_of_B_1.is_OK()); + lp_assert(! use_tableau()); + lp_assert(m_pivot_row_of_B_1.is_OK()); m_pivot_row_of_B_1.clear(); m_pivot_row_of_B_1.set_value(numeric_traits::one(), pivot_row); - lean_assert(m_pivot_row_of_B_1.is_OK()); + lp_assert(m_pivot_row_of_B_1.is_OK()); m_factorization->solve_yB_with_error_check_indexed(m_pivot_row_of_B_1, m_basis_heading, m_basis, m_settings); - lean_assert(m_pivot_row_of_B_1.is_OK()); + lp_assert(m_pivot_row_of_B_1.is_OK()); } @@ -380,11 +380,11 @@ set_non_basic_x_to_correct_bounds() { break; case column_type::low_bound: m_x[j] = m_low_bounds[j]; - lean_assert(column_is_dual_feasible(j)); + lp_assert(column_is_dual_feasible(j)); break; case column_type::upper_bound: m_x[j] = m_upper_bounds[j]; - lean_assert(column_is_dual_feasible(j)); + lp_assert(column_is_dual_feasible(j)); break; default: break; @@ -402,15 +402,15 @@ column_is_dual_feasible(unsigned j) const { return x_is_at_low_bound(j) && d_is_not_negative(j); case column_type::upper_bound: LP_OUT(m_settings, "upper_bound type should be switched to low_bound" << std::endl); - lean_assert(false); // impossible case + lp_assert(false); // impossible case case column_type::free_column: return numeric_traits::is_zero(m_d[j]); default: LP_OUT(m_settings, "column = " << j << std::endl); LP_OUT(m_settings, "unexpected column type = " << column_type_to_string(m_column_types[j]) << std::endl); - lean_unreachable(); + lp_unreachable(); } - lean_unreachable(); + lp_unreachable(); return false; } template bool lp_core_solver_base:: @@ -493,7 +493,7 @@ template bool lp_core_solver_base::column_is_feas return true; break; default: - lean_unreachable(); + lp_unreachable(); } return false; // it is unreachable } @@ -575,7 +575,7 @@ update_basis_and_x(int entering, int leaving, X const & tt) { restore_x_and_refactor(entering, leaving, tt); if (m_status == FLOATING_POINT_ERROR) return false; - lean_assert(!A_mult_x_is_off()); + lp_assert(!A_mult_x_is_off()); m_iters_with_no_cost_growing++; // LP_OUT(m_settings, "rolled back after failing of init_factorization()" << std::endl); m_status = UNSTABLE; @@ -587,7 +587,7 @@ update_basis_and_x(int entering, int leaving, X const & tt) { template bool lp_core_solver_base:: divide_row_by_pivot(unsigned pivot_row, unsigned pivot_col) { - lean_assert(numeric_traits::precise()); + lp_assert(numeric_traits::precise()); int pivot_index = -1; auto & row = m_A.m_rows[pivot_row]; unsigned size = row.size(); @@ -628,7 +628,7 @@ pivot_column_tableau(unsigned j, unsigned piv_row_index) { return false; if (pivot_col_cell_index != 0) { - lean_assert(column.size() > 1); + lp_assert(column.size() > 1); // swap the pivot column cell with the head cell auto c = column[0]; column[0] = column[pivot_col_cell_index]; @@ -639,7 +639,7 @@ pivot_column_tableau(unsigned j, unsigned piv_row_index) { } while (column.size() > 1) { auto & c = column.back(); - lean_assert(c.m_i != piv_row_index); + lp_assert(c.m_i != piv_row_index); if(! m_A.pivot_row_to_row_given_cell(piv_row_index, c, j)) { return false; } @@ -687,7 +687,7 @@ non_basis_is_correctly_represented_in_heading() const { } for (unsigned j = 0; j < m_A.column_count(); j++) { if (m_basis_heading[j] >= 0) { - lean_assert(static_cast(m_basis_heading[j]) < m_A.row_count() && m_basis[m_basis_heading[j]] == j); + lp_assert(static_cast(m_basis_heading[j]) < m_A.row_count() && m_basis[m_basis_heading[j]] == j); } } return true; @@ -695,9 +695,9 @@ non_basis_is_correctly_represented_in_heading() const { template bool lp_core_solver_base:: basis_heading_is_correct() const { - lean_assert(m_basis_heading.size() == m_A.column_count()); - lean_assert(m_basis.size() == m_A.row_count()); - lean_assert(m_nbasis.size() <= m_A.column_count() - m_A.row_count()); // for the dual the size of non basis can be smaller + lp_assert(m_basis_heading.size() == m_A.column_count()); + lp_assert(m_basis.size() == m_A.row_count()); + lp_assert(m_nbasis.size() <= m_A.column_count() - m_A.row_count()); // for the dual the size of non basis can be smaller if (!basis_has_no_doubles()) { // std::cout << "basis_has_no_doubles" << std::endl; return false; @@ -841,7 +841,7 @@ solve_Ax_eq_b() { template void lp_core_solver_base:: snap_non_basic_x_to_bound_and_free_to_zeroes() { for (unsigned j : non_basis()) { - lean_assert(j < m_x.size()); + lp_assert(j < m_x.size()); switch (m_column_types[j]) { case column_type::fixed: case column_type::boxed: @@ -892,9 +892,9 @@ get_non_basic_column_value_position(unsigned j) const { case column_type::upper_bound: return x_is_at_upper_bound(j)? at_upper_bound : not_at_bound; default: - lean_unreachable(); + lp_unreachable(); } - lean_unreachable(); + lp_unreachable(); return at_low_bound; } @@ -925,8 +925,8 @@ template void lp_core_solver_base::transpose_row } // j is the new basic column, j_basic - the leaving column template bool lp_core_solver_base::pivot_column_general(unsigned j, unsigned j_basic, indexed_vector & w) { - lean_assert(m_basis_heading[j] < 0); - lean_assert(m_basis_heading[j_basic] >= 0); + lp_assert(m_basis_heading[j] < 0); + lp_assert(m_basis_heading[j_basic] >= 0); unsigned row_index = m_basis_heading[j_basic]; if (m_settings.m_simplex_strategy == simplex_strategy_enum::lu) { if (m_factorization->need_to_refactor()) { @@ -980,7 +980,7 @@ template bool lp_core_solver_base::infeasibility_costs_are_correct() const { if (! this->m_using_infeas_costs) return true; - lean_assert(costs_on_nbasis_are_zeros()); + lp_assert(costs_on_nbasis_are_zeros()); for (unsigned j :this->m_basis) { if (!infeasibility_cost_is_correct_for_column(j)) { std::cout << "infeasibility_cost_is_correct_for_column does not hold\n"; @@ -1025,15 +1025,15 @@ lp_core_solver_base::infeasibility_cost_is_correct_for_column(unsigned j) case column_type::free_column: return is_zero(this->m_costs[j]); default: - lean_assert(false); + lp_assert(false); return true; } } template void lp_core_solver_base::calculate_pivot_row(unsigned i) { - lean_assert(!use_tableau()); - lean_assert(m_pivot_row.is_OK()); + lp_assert(!use_tableau()); + lp_assert(m_pivot_row.is_OK()); m_pivot_row_of_B_1.clear(); m_pivot_row_of_B_1.resize(m_m()); m_pivot_row.clear(); diff --git a/src/util/lp/lp_core_solver_base_instances.cpp b/src/util/lp/lp_core_solver_base_instances.cpp index d473594c8..1f9d459bf 100644 --- a/src/util/lp/lp_core_solver_base_instances.cpp +++ b/src/util/lp/lp_core_solver_base_instances.cpp @@ -8,125 +8,125 @@ #include "util/vector.h" #include #include "util/lp/lp_core_solver_base.hpp" -template bool lean::lp_core_solver_base::A_mult_x_is_off() const; -template bool lean::lp_core_solver_base::A_mult_x_is_off_on_index(const vector &) const; -template bool lean::lp_core_solver_base::basis_heading_is_correct() const; -template void lean::lp_core_solver_base::calculate_pivot_row_of_B_1(unsigned int); -template void lean::lp_core_solver_base::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); -template bool lean::lp_core_solver_base::column_is_dual_feasible(unsigned int) const; -template void lean::lp_core_solver_base::fill_reduced_costs_from_m_y_by_rows(); -template bool lean::lp_core_solver_base::find_x_by_solving(); -template lean::non_basic_column_value_position lean::lp_core_solver_base::get_non_basic_column_value_position(unsigned int) const; -template lean::non_basic_column_value_position lean::lp_core_solver_base >::get_non_basic_column_value_position(unsigned int) const; -template lean::non_basic_column_value_position lean::lp_core_solver_base::get_non_basic_column_value_position(unsigned int) const; -template void lean::lp_core_solver_base::init_reduced_costs_for_one_iteration(); -template lean::lp_core_solver_base::lp_core_solver_base( - lean::static_matrix&, vector&, +template bool lp::lp_core_solver_base::A_mult_x_is_off() const; +template bool lp::lp_core_solver_base::A_mult_x_is_off_on_index(const vector &) const; +template bool lp::lp_core_solver_base::basis_heading_is_correct() const; +template void lp::lp_core_solver_base::calculate_pivot_row_of_B_1(unsigned int); +template void lp::lp_core_solver_base::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); +template bool lp::lp_core_solver_base::column_is_dual_feasible(unsigned int) const; +template void lp::lp_core_solver_base::fill_reduced_costs_from_m_y_by_rows(); +template bool lp::lp_core_solver_base::find_x_by_solving(); +template lp::non_basic_column_value_position lp::lp_core_solver_base::get_non_basic_column_value_position(unsigned int) const; +template lp::non_basic_column_value_position lp::lp_core_solver_base >::get_non_basic_column_value_position(unsigned int) const; +template lp::non_basic_column_value_position lp::lp_core_solver_base::get_non_basic_column_value_position(unsigned int) const; +template void lp::lp_core_solver_base::init_reduced_costs_for_one_iteration(); +template lp::lp_core_solver_base::lp_core_solver_base( + lp::static_matrix&, vector&, vector&, vector &, vector &, vector&, vector&, - lean::lp_settings&, const column_namer&, const vector&, + lp::lp_settings&, const column_namer&, const vector&, const vector&, const vector&); -template bool lean::lp_core_solver_base::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); -template bool lean::lp_core_solver_base >::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); -template void lean::lp_core_solver_base::restore_x(unsigned int, double const&); -template void lean::lp_core_solver_base::set_non_basic_x_to_correct_bounds(); -template void lean::lp_core_solver_base::snap_xN_to_bounds_and_free_columns_to_zeroes(); -template void lean::lp_core_solver_base >::snap_xN_to_bounds_and_free_columns_to_zeroes(); -template void lean::lp_core_solver_base::solve_Ax_eq_b(); -template void lean::lp_core_solver_base::solve_Bd(unsigned int); -template void lean::lp_core_solver_base>::solve_Bd(unsigned int, indexed_vector&); -template void lean::lp_core_solver_base::solve_yB(vector&); -template bool lean::lp_core_solver_base::update_basis_and_x(int, int, double const&); -template void lean::lp_core_solver_base::update_x(unsigned int, const double&); -template bool lean::lp_core_solver_base::A_mult_x_is_off() const; -template bool lean::lp_core_solver_base::A_mult_x_is_off_on_index(const vector &) const; -template bool lean::lp_core_solver_base::basis_heading_is_correct() const ; -template void lean::lp_core_solver_base::calculate_pivot_row_of_B_1(unsigned int); -template void lean::lp_core_solver_base::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); -template bool lean::lp_core_solver_base::column_is_dual_feasible(unsigned int) const; -template void lean::lp_core_solver_base::fill_reduced_costs_from_m_y_by_rows(); -template bool lean::lp_core_solver_base::find_x_by_solving(); -template void lean::lp_core_solver_base::init_reduced_costs_for_one_iteration(); -template bool lean::lp_core_solver_base::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); -template void lean::lp_core_solver_base::restore_x(unsigned int, lean::mpq const&); -template void lean::lp_core_solver_base::set_non_basic_x_to_correct_bounds(); -template void lean::lp_core_solver_base::solve_Ax_eq_b(); -template void lean::lp_core_solver_base::solve_Bd(unsigned int); -template void lean::lp_core_solver_base::solve_yB(vector&); -template bool lean::lp_core_solver_base::update_basis_and_x(int, int, lean::mpq const&); -template void lean::lp_core_solver_base::update_x(unsigned int, const lean::mpq&); -template void lean::lp_core_solver_base >::calculate_pivot_row_of_B_1(unsigned int); -template void lean::lp_core_solver_base >::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); -template void lean::lp_core_solver_base >::init(); -template void lean::lp_core_solver_base >::init_basis_heading_and_non_basic_columns_vector(); -template void lean::lp_core_solver_base >::init_reduced_costs_for_one_iteration(); -template lean::lp_core_solver_base >::lp_core_solver_base(lean::static_matrix >&, vector >&, vector&, vector &, vector &, vector >&, vector&, lean::lp_settings&, const column_namer&, const vector&, - const vector >&, - const vector >&); -template bool lean::lp_core_solver_base >::print_statistics_with_cost_and_check_that_the_time_is_over(lean::numeric_pair, std::ostream&); -template void lean::lp_core_solver_base >::snap_xN_to_bounds_and_fill_xB(); -template void lean::lp_core_solver_base >::solve_Bd(unsigned int); -template bool lean::lp_core_solver_base >::update_basis_and_x(int, int, lean::numeric_pair const&); -template void lean::lp_core_solver_base >::update_x(unsigned int, const lean::numeric_pair&); -template lean::lp_core_solver_base::lp_core_solver_base( - lean::static_matrix&, - vector&, +template bool lp::lp_core_solver_base::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); +template bool lp::lp_core_solver_base >::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); +template void lp::lp_core_solver_base::restore_x(unsigned int, double const&); +template void lp::lp_core_solver_base::set_non_basic_x_to_correct_bounds(); +template void lp::lp_core_solver_base::snap_xN_to_bounds_and_free_columns_to_zeroes(); +template void lp::lp_core_solver_base >::snap_xN_to_bounds_and_free_columns_to_zeroes(); +template void lp::lp_core_solver_base::solve_Ax_eq_b(); +template void lp::lp_core_solver_base::solve_Bd(unsigned int); +template void lp::lp_core_solver_base>::solve_Bd(unsigned int, indexed_vector&); +template void lp::lp_core_solver_base::solve_yB(vector&); +template bool lp::lp_core_solver_base::update_basis_and_x(int, int, double const&); +template void lp::lp_core_solver_base::update_x(unsigned int, const double&); +template bool lp::lp_core_solver_base::A_mult_x_is_off() const; +template bool lp::lp_core_solver_base::A_mult_x_is_off_on_index(const vector &) const; +template bool lp::lp_core_solver_base::basis_heading_is_correct() const ; +template void lp::lp_core_solver_base::calculate_pivot_row_of_B_1(unsigned int); +template void lp::lp_core_solver_base::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); +template bool lp::lp_core_solver_base::column_is_dual_feasible(unsigned int) const; +template void lp::lp_core_solver_base::fill_reduced_costs_from_m_y_by_rows(); +template bool lp::lp_core_solver_base::find_x_by_solving(); +template void lp::lp_core_solver_base::init_reduced_costs_for_one_iteration(); +template bool lp::lp_core_solver_base::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &); +template void lp::lp_core_solver_base::restore_x(unsigned int, lp::mpq const&); +template void lp::lp_core_solver_base::set_non_basic_x_to_correct_bounds(); +template void lp::lp_core_solver_base::solve_Ax_eq_b(); +template void lp::lp_core_solver_base::solve_Bd(unsigned int); +template void lp::lp_core_solver_base::solve_yB(vector&); +template bool lp::lp_core_solver_base::update_basis_and_x(int, int, lp::mpq const&); +template void lp::lp_core_solver_base::update_x(unsigned int, const lp::mpq&); +template void lp::lp_core_solver_base >::calculate_pivot_row_of_B_1(unsigned int); +template void lp::lp_core_solver_base >::calculate_pivot_row_when_pivot_row_of_B1_is_ready(unsigned); +template void lp::lp_core_solver_base >::init(); +template void lp::lp_core_solver_base >::init_basis_heading_and_non_basic_columns_vector(); +template void lp::lp_core_solver_base >::init_reduced_costs_for_one_iteration(); +template lp::lp_core_solver_base >::lp_core_solver_base(lp::static_matrix >&, vector >&, vector&, vector &, vector &, vector >&, vector&, lp::lp_settings&, const column_namer&, const vector&, + const vector >&, + const vector >&); +template bool lp::lp_core_solver_base >::print_statistics_with_cost_and_check_that_the_time_is_over(lp::numeric_pair, std::ostream&); +template void lp::lp_core_solver_base >::snap_xN_to_bounds_and_fill_xB(); +template void lp::lp_core_solver_base >::solve_Bd(unsigned int); +template bool lp::lp_core_solver_base >::update_basis_and_x(int, int, lp::numeric_pair const&); +template void lp::lp_core_solver_base >::update_x(unsigned int, const lp::numeric_pair&); +template lp::lp_core_solver_base::lp_core_solver_base( + lp::static_matrix&, + vector&, vector&, vector &, vector &, - vector&, - vector&, - lean::lp_settings&, + vector&, + vector&, + lp::lp_settings&, const column_namer&, - const vector&, - const vector&, - const vector&); -template bool lean::lp_core_solver_base >::print_statistics_with_iterations_and_check_that_the_time_is_over(std::ostream &); -template std::string lean::lp_core_solver_base::column_name(unsigned int) const; -template void lean::lp_core_solver_base::pretty_print(std::ostream & out); -template void lean::lp_core_solver_base::restore_state(double*, double*); -template void lean::lp_core_solver_base::save_state(double*, double*); -template std::string lean::lp_core_solver_base::column_name(unsigned int) const; -template void lean::lp_core_solver_base::pretty_print(std::ostream & out); -template void lean::lp_core_solver_base::restore_state(lean::mpq*, lean::mpq*); -template void lean::lp_core_solver_base::save_state(lean::mpq*, lean::mpq*); -template std::string lean::lp_core_solver_base >::column_name(unsigned int) const; -template void lean::lp_core_solver_base >::pretty_print(std::ostream & out); -template void lean::lp_core_solver_base >::restore_state(lean::mpq*, lean::mpq*); -template void lean::lp_core_solver_base >::save_state(lean::mpq*, lean::mpq*); -template void lean::lp_core_solver_base >::solve_yB(vector&); -template void lean::lp_core_solver_base::init_lu(); -template void lean::lp_core_solver_base::init_lu(); -template int lean::lp_core_solver_base::pivots_in_column_and_row_are_different(int, int) const; -template int lean::lp_core_solver_base >::pivots_in_column_and_row_are_different(int, int) const; -template int lean::lp_core_solver_base::pivots_in_column_and_row_are_different(int, int) const; -template bool lean::lp_core_solver_base::calc_current_x_is_feasible_include_non_basis(void)const; -template bool lean::lp_core_solver_base::calc_current_x_is_feasible_include_non_basis(void)const; -template bool lean::lp_core_solver_base >::calc_current_x_is_feasible_include_non_basis() const; -template void lean::lp_core_solver_base >::pivot_fixed_vars_from_basis(); -template bool lean::lp_core_solver_base::column_is_feasible(unsigned int) const; -template bool lean::lp_core_solver_base::column_is_feasible(unsigned int) const; -// template void lean::lp_core_solver_base >::print_linear_combination_of_column_indices(vector, std::allocator > > const&, std::ostream&) const; -template bool lean::lp_core_solver_base >::column_is_feasible(unsigned int) const; -template bool lean::lp_core_solver_base >::snap_non_basic_x_to_bound(); -template void lean::lp_core_solver_base >::init_lu(); -template bool lean::lp_core_solver_base >::A_mult_x_is_off_on_index(vector const&) const; -template bool lean::lp_core_solver_base >::find_x_by_solving(); -template void lean::lp_core_solver_base >::restore_x(unsigned int, lean::numeric_pair const&); -template bool lean::lp_core_solver_base::pivot_for_tableau_on_basis(); -template bool lean::lp_core_solver_base::pivot_for_tableau_on_basis(); -template bool lean::lp_core_solver_base>::pivot_for_tableau_on_basis(); -template bool lean::lp_core_solver_base>::pivot_column_tableau(unsigned int, unsigned int); -template bool lean::lp_core_solver_base::pivot_column_tableau(unsigned int, unsigned int); -template bool lean::lp_core_solver_base::pivot_column_tableau(unsigned int, unsigned int); -template void lean::lp_core_solver_base >::transpose_rows_tableau(unsigned int, unsigned int); -template bool lean::lp_core_solver_base >::inf_set_is_correct() const; -template bool lean::lp_core_solver_base::inf_set_is_correct() const; -template bool lean::lp_core_solver_base::inf_set_is_correct() const; -template bool lean::lp_core_solver_base >::infeasibility_costs_are_correct() const; -template bool lean::lp_core_solver_base::infeasibility_costs_are_correct() const; -template bool lean::lp_core_solver_base::infeasibility_costs_are_correct() const; -template void lean::lp_core_solver_base >::calculate_pivot_row(unsigned int); + const vector&, + const vector&, + const vector&); +template bool lp::lp_core_solver_base >::print_statistics_with_iterations_and_check_that_the_time_is_over(std::ostream &); +template std::string lp::lp_core_solver_base::column_name(unsigned int) const; +template void lp::lp_core_solver_base::pretty_print(std::ostream & out); +template void lp::lp_core_solver_base::restore_state(double*, double*); +template void lp::lp_core_solver_base::save_state(double*, double*); +template std::string lp::lp_core_solver_base::column_name(unsigned int) const; +template void lp::lp_core_solver_base::pretty_print(std::ostream & out); +template void lp::lp_core_solver_base::restore_state(lp::mpq*, lp::mpq*); +template void lp::lp_core_solver_base::save_state(lp::mpq*, lp::mpq*); +template std::string lp::lp_core_solver_base >::column_name(unsigned int) const; +template void lp::lp_core_solver_base >::pretty_print(std::ostream & out); +template void lp::lp_core_solver_base >::restore_state(lp::mpq*, lp::mpq*); +template void lp::lp_core_solver_base >::save_state(lp::mpq*, lp::mpq*); +template void lp::lp_core_solver_base >::solve_yB(vector&); +template void lp::lp_core_solver_base::init_lu(); +template void lp::lp_core_solver_base::init_lu(); +template int lp::lp_core_solver_base::pivots_in_column_and_row_are_different(int, int) const; +template int lp::lp_core_solver_base >::pivots_in_column_and_row_are_different(int, int) const; +template int lp::lp_core_solver_base::pivots_in_column_and_row_are_different(int, int) const; +template bool lp::lp_core_solver_base::calc_current_x_is_feasible_include_non_basis(void)const; +template bool lp::lp_core_solver_base::calc_current_x_is_feasible_include_non_basis(void)const; +template bool lp::lp_core_solver_base >::calc_current_x_is_feasible_include_non_basis() const; +template void lp::lp_core_solver_base >::pivot_fixed_vars_from_basis(); +template bool lp::lp_core_solver_base::column_is_feasible(unsigned int) const; +template bool lp::lp_core_solver_base::column_is_feasible(unsigned int) const; +// template void lp::lp_core_solver_base >::print_linear_combination_of_column_indices(vector, std::allocator > > const&, std::ostream&) const; +template bool lp::lp_core_solver_base >::column_is_feasible(unsigned int) const; +template bool lp::lp_core_solver_base >::snap_non_basic_x_to_bound(); +template void lp::lp_core_solver_base >::init_lu(); +template bool lp::lp_core_solver_base >::A_mult_x_is_off_on_index(vector const&) const; +template bool lp::lp_core_solver_base >::find_x_by_solving(); +template void lp::lp_core_solver_base >::restore_x(unsigned int, lp::numeric_pair const&); +template bool lp::lp_core_solver_base::pivot_for_tableau_on_basis(); +template bool lp::lp_core_solver_base::pivot_for_tableau_on_basis(); +template bool lp::lp_core_solver_base>::pivot_for_tableau_on_basis(); +template bool lp::lp_core_solver_base>::pivot_column_tableau(unsigned int, unsigned int); +template bool lp::lp_core_solver_base::pivot_column_tableau(unsigned int, unsigned int); +template bool lp::lp_core_solver_base::pivot_column_tableau(unsigned int, unsigned int); +template void lp::lp_core_solver_base >::transpose_rows_tableau(unsigned int, unsigned int); +template bool lp::lp_core_solver_base >::inf_set_is_correct() const; +template bool lp::lp_core_solver_base::inf_set_is_correct() const; +template bool lp::lp_core_solver_base::inf_set_is_correct() const; +template bool lp::lp_core_solver_base >::infeasibility_costs_are_correct() const; +template bool lp::lp_core_solver_base::infeasibility_costs_are_correct() const; +template bool lp::lp_core_solver_base::infeasibility_costs_are_correct() const; +template void lp::lp_core_solver_base >::calculate_pivot_row(unsigned int); diff --git a/src/util/lp/lp_dual_core_solver.h b/src/util/lp/lp_dual_core_solver.h index b873cb711..71a00c268 100644 --- a/src/util/lp/lp_dual_core_solver.h +++ b/src/util/lp/lp_dual_core_solver.h @@ -11,7 +11,7 @@ #include #include "util/vector.h" -namespace lean { +namespace lp { template class lp_dual_core_solver:public lp_core_solver_base { public: diff --git a/src/util/lp/lp_dual_core_solver.hpp b/src/util/lp/lp_dual_core_solver.hpp index 6565331b3..5038fc4ea 100644 --- a/src/util/lp/lp_dual_core_solver.hpp +++ b/src/util/lp/lp_dual_core_solver.hpp @@ -7,7 +7,7 @@ #include "util/vector.h" #include "util/lp/lp_dual_core_solver.h" -namespace lean { +namespace lp { template void lp_dual_core_solver::init_a_wave_by_zeros() { unsigned j = this->m_m(); @@ -23,7 +23,7 @@ template void lp_dual_core_solver::restore_non_ba while (j--) { if (this->m_basis_heading[j] >= 0 ) continue; if (m_can_enter_basis[j]) { - lean_assert(std::find(nb.begin(), nb.end(), j) == nb.end()); + lp_assert(std::find(nb.begin(), nb.end(), j) == nb.end()); nb.push_back(j); this->m_basis_heading[j] = - static_cast(nb.size()); } @@ -93,14 +93,14 @@ template bool lp_dual_core_solver::done() { } template T lp_dual_core_solver::get_edge_steepness_for_low_bound(unsigned p) { - lean_assert(this->m_basis_heading[p] >= 0 && static_cast(this->m_basis_heading[p]) < this->m_m()); + lp_assert(this->m_basis_heading[p] >= 0 && static_cast(this->m_basis_heading[p]) < this->m_m()); T del = this->m_x[p] - this->m_low_bounds[p]; del *= del; return del / this->m_betas[this->m_basis_heading[p]]; } template T lp_dual_core_solver::get_edge_steepness_for_upper_bound(unsigned p) { - lean_assert(this->m_basis_heading[p] >= 0 && static_cast(this->m_basis_heading[p]) < this->m_m()); + lp_assert(this->m_basis_heading[p] >= 0 && static_cast(this->m_basis_heading[p]) < this->m_m()); T del = this->m_x[p] - this->m_upper_bounds[p]; del *= del; return del / this->m_betas[this->m_basis_heading[p]]; @@ -135,12 +135,12 @@ template T lp_dual_core_solver::pricing_for_row(u return numeric_traits::zero(); break; case column_type::free_column: - lean_assert(numeric_traits::is_zero(this->m_d[p])); + lp_assert(numeric_traits::is_zero(this->m_d[p])); return numeric_traits::zero(); default: - lean_unreachable(); + lp_unreachable(); } - lean_unreachable(); + lp_unreachable(); return numeric_traits::zero(); } @@ -209,9 +209,9 @@ template bool lp_dual_core_solver::advance_on_kno int pivot_compare_result = this->pivots_in_column_and_row_are_different(m_q, m_p); if (!pivot_compare_result){;} else if (pivot_compare_result == 2) { // the sign is changed, cannot continue - lean_unreachable(); // not implemented yet + lp_unreachable(); // not implemented yet } else { - lean_assert(pivot_compare_result == 1); + lp_assert(pivot_compare_result == 1); this->init_lu(); } DSE_FTran(); @@ -228,21 +228,21 @@ template int lp_dual_core_solver::define_sign_of_ if (this->x_above_upper_bound(m_p)) { return 1; } - lean_unreachable(); + lp_unreachable(); case column_type::low_bound: if (this->x_below_low_bound(m_p)) { return -1; } - lean_unreachable(); + lp_unreachable(); case column_type::upper_bound: if (this->x_above_upper_bound(m_p)) { return 1; } - lean_unreachable(); + lp_unreachable(); default: - lean_unreachable(); + lp_unreachable(); } - lean_unreachable(); + lp_unreachable(); return 0; } @@ -250,10 +250,10 @@ template bool lp_dual_core_solver::can_be_breakpo if (this->pivot_row_element_is_too_small_for_ratio_test(j)) return false; switch (this->m_column_types[j]) { case column_type::low_bound: - lean_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_low_bounds[j])); return m_sign_of_alpha_r * this->m_pivot_row[j] > 0; case column_type::upper_bound: - lean_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; case column_type::boxed: { @@ -292,23 +292,23 @@ template T lp_dual_core_solver::get_delta() { if (this->x_above_upper_bound(m_p)) { return this->m_x[m_p] - this->m_upper_bounds[m_p]; } - lean_unreachable(); + lp_unreachable(); case column_type::low_bound: if (this->x_below_low_bound(m_p)) { return this->m_x[m_p] - this->m_low_bounds[m_p]; } - lean_unreachable(); + lp_unreachable(); case column_type::upper_bound: if (this->x_above_upper_bound(m_p)) { return get_edge_steepness_for_upper_bound(m_p); } - lean_unreachable(); + lp_unreachable(); case column_type::fixed: return this->m_x[m_p] - this->m_upper_bounds[m_p]; default: - lean_unreachable(); + lp_unreachable(); } - lean_unreachable(); + lp_unreachable(); return zero_of_type(); } @@ -355,7 +355,7 @@ template void lp_dual_core_solver::update_betas() template void lp_dual_core_solver::apply_flips() { for (unsigned j : m_flipped_boxed) { - lean_assert(this->x_is_at_bound(j)); + lp_assert(this->x_is_at_bound(j)); if (this->x_is_at_low_bound(j)) { this->m_x[j] = this->m_upper_bounds[j]; } else { @@ -385,7 +385,7 @@ template void lp_dual_core_solver::snap_xN_column case column_type::free_column: break; default: - lean_unreachable(); + lp_unreachable(); } } @@ -441,7 +441,7 @@ template bool lp_dual_core_solver::basis_change_a return false; } - lean_assert(d_is_correct()); + lp_assert(d_is_correct()); return true; } @@ -457,7 +457,7 @@ template void lp_dual_core_solver::recover_leavin case free_of_bounds: this->m_x[m_q] = zero_of_type(); default: - lean_unreachable(); + lp_unreachable(); } } @@ -584,7 +584,7 @@ template bool lp_dual_core_solver::tight_breakpoi template T lp_dual_core_solver::calculate_harris_delta_on_breakpoint_set() { bool first_time = true; T ret = zero_of_type(); - lean_assert(m_breakpoint_set.size() > 0); + lp_assert(m_breakpoint_set.size() > 0); for (auto j : m_breakpoint_set) { T t; if (this->x_is_at_low_bound(j)) { @@ -633,7 +633,7 @@ template void lp_dual_core_solver::find_q_on_tigh } } m_tight_set.erase(m_q); - lean_assert(m_q != -1); + lp_assert(m_q != -1); } template void lp_dual_core_solver::find_q_and_tight_set() { @@ -722,13 +722,13 @@ template void lp_dual_core_solver::one_iteration( this->set_status(FEASIBLE); } pricing_loop(number_of_rows_to_try, offset_in_rows); - lean_assert(problem_is_dual_feasible()); + lp_assert(problem_is_dual_feasible()); } template void lp_dual_core_solver::solve() { // see the page 35 - lean_assert(d_is_correct()); - lean_assert(problem_is_dual_feasible()); - lean_assert(this->basis_heading_is_correct()); + lp_assert(d_is_correct()); + lp_assert(problem_is_dual_feasible()); + lp_assert(this->basis_heading_is_correct()); this->set_total_iterations(0); this->iters_with_no_cost_growing() = 0; do { diff --git a/src/util/lp/lp_dual_core_solver_instances.cpp b/src/util/lp/lp_dual_core_solver_instances.cpp index 8016088f8..9484d34a3 100644 --- a/src/util/lp/lp_dual_core_solver_instances.cpp +++ b/src/util/lp/lp_dual_core_solver_instances.cpp @@ -8,22 +8,22 @@ #include "util/vector.h" #include #include "util/lp/lp_dual_core_solver.hpp" -template void lean::lp_dual_core_solver::start_with_initial_basis_and_make_it_dual_feasible(); -template void lean::lp_dual_core_solver::solve(); -template lean::lp_dual_core_solver::lp_dual_core_solver(lean::static_matrix&, vector&, +template void lp::lp_dual_core_solver::start_with_initial_basis_and_make_it_dual_feasible(); +template void lp::lp_dual_core_solver::solve(); +template lp::lp_dual_core_solver::lp_dual_core_solver(lp::static_matrix&, vector&, vector&, vector&, vector&, vector &, vector &, vector&, - vector&, + vector&, vector&, vector&, - lean::lp_settings&, const lean::column_namer&); -template void lean::lp_dual_core_solver::start_with_initial_basis_and_make_it_dual_feasible(); -template void lean::lp_dual_core_solver::solve(); -template void lean::lp_dual_core_solver::restore_non_basis(); -template void lean::lp_dual_core_solver::restore_non_basis(); -template void lean::lp_dual_core_solver::revert_to_previous_basis(); -template void lean::lp_dual_core_solver::revert_to_previous_basis(); + lp::lp_settings&, const lp::column_namer&); +template void lp::lp_dual_core_solver::start_with_initial_basis_and_make_it_dual_feasible(); +template void lp::lp_dual_core_solver::solve(); +template void lp::lp_dual_core_solver::restore_non_basis(); +template void lp::lp_dual_core_solver::restore_non_basis(); +template void lp::lp_dual_core_solver::revert_to_previous_basis(); +template void lp::lp_dual_core_solver::revert_to_previous_basis(); diff --git a/src/util/lp/lp_dual_simplex.h b/src/util/lp/lp_dual_simplex.h index 4dff2a4f1..58d9b7240 100644 --- a/src/util/lp/lp_dual_simplex.h +++ b/src/util/lp/lp_dual_simplex.h @@ -7,7 +7,7 @@ #include "util/lp/lp_utils.h" #include "util/lp/lp_solver.h" #include "util/lp/lp_dual_core_solver.h" -namespace lean { +namespace lp { template class lp_dual_simplex: public lp_solver { diff --git a/src/util/lp/lp_dual_simplex.hpp b/src/util/lp/lp_dual_simplex.hpp index 5047e117f..8e16853a8 100644 --- a/src/util/lp/lp_dual_simplex.hpp +++ b/src/util/lp/lp_dual_simplex.hpp @@ -3,7 +3,7 @@ Author: Lev Nachmanson */ #include "util/lp/lp_dual_simplex.h" -namespace lean{ +namespace lp{ template void lp_dual_simplex::decide_on_status_after_stage1() { switch (m_core_solver->get_status()) { @@ -15,7 +15,7 @@ template void lp_dual_simplex::decide_on_status_a } break; case DUAL_UNBOUNDED: - lean_unreachable(); + lp_unreachable(); case ITERATIONS_EXHAUSTED: this->m_status = ITERATIONS_EXHAUSTED; break; @@ -26,12 +26,12 @@ template void lp_dual_simplex::decide_on_status_a this->m_status = FLOATING_POINT_ERROR; break; default: - lean_unreachable(); + lp_unreachable(); } } template void lp_dual_simplex::fix_logical_for_stage2(unsigned j) { - lean_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()]) { case column_type::low_bound: m_low_bounds[j] = numeric_traits::zero(); @@ -44,7 +44,7 @@ template void lp_dual_simplex::fix_logical_for_st m_can_enter_basis[j] = false; break; default: - lean_unreachable(); + lp_unreachable(); } } @@ -58,7 +58,7 @@ template void lp_dual_simplex::fix_structural_for break; case column_type::fixed: case column_type::upper_bound: - lean_unreachable(); + lp_unreachable(); case column_type::boxed: this->m_upper_bounds[j] = ci->get_adjusted_upper_bound() / this->m_column_scale[j]; m_low_bounds[j] = numeric_traits::zero(); @@ -70,7 +70,7 @@ template void lp_dual_simplex::fix_structural_for m_column_types_of_core_solver[j] = column_type::free_column; break; default: - lean_unreachable(); + lp_unreachable(); } // T cost_was = this->m_costs[j]; this->set_scaled_cost(j); @@ -115,7 +115,7 @@ template void lp_dual_simplex::solve_for_stage2() this->m_status = FLOATING_POINT_ERROR; break; default: - lean_unreachable(); + lp_unreachable(); } this->m_second_stage_iterations = m_core_solver->total_iterations(); this->m_total_iterations = (this->m_first_stage_iterations + this->m_second_stage_iterations); @@ -129,7 +129,7 @@ template void lp_dual_simplex::fill_x_with_zeros( } template void lp_dual_simplex::stage1() { - lean_assert(m_core_solver == nullptr); + lp_assert(m_core_solver == nullptr); this->m_x.resize(this->m_A->column_count(), numeric_traits::zero()); if (this->m_settings.get_message_ostream() != nullptr) this->print_statistics_on_A(*this->m_settings.get_message_ostream()); @@ -177,7 +177,7 @@ template void lp_dual_simplex::fill_first_stage_s } template column_type lp_dual_simplex::get_column_type(unsigned j) { - lean_assert(j < this->m_A->column_count()); + lp_assert(j < this->m_A->column_count()); if (j >= this->number_of_core_structurals()) { return m_column_types_of_logicals[j - this->number_of_core_structurals()]; } @@ -186,12 +186,12 @@ template column_type lp_dual_simplex::get_column_ template void lp_dual_simplex::fill_costs_bounds_types_and_can_enter_basis_for_the_first_stage_solver_structural_column(unsigned j) { // see 4.7 in the dissertation of Achim Koberstein - lean_assert(this->m_core_solver_columns_to_external_columns.find(j) != + lp_assert(this->m_core_solver_columns_to_external_columns.find(j) != this->m_core_solver_columns_to_external_columns.end()); T free_bound = T(1e4); // see 4.8 unsigned jj = this->m_core_solver_columns_to_external_columns[j]; - lean_assert(this->m_map_from_var_index_to_column_info.find(jj) != this->m_map_from_var_index_to_column_info.end()); + lp_assert(this->m_map_from_var_index_to_column_info.find(jj) != this->m_map_from_var_index_to_column_info.end()); column_info * ci = this->m_map_from_var_index_to_column_info[jj]; switch (ci->get_column_type()) { case column_type::upper_bound: { @@ -221,14 +221,14 @@ template void lp_dual_simplex::fill_costs_bounds_ this->m_upper_bounds[j] = this->m_low_bounds[j] = numeric_traits::zero(); // is it needed? break; default: - lean_unreachable(); + lp_unreachable(); } m_column_types_of_core_solver[j] = column_type::boxed; } template void lp_dual_simplex::fill_costs_bounds_types_and_can_enter_basis_for_the_first_stage_solver_logical_column(unsigned j) { this->m_costs[j] = 0; - lean_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))) { m_column_types_of_core_solver[j] = column_type::boxed; this->m_low_bounds[j] = numeric_traits::zero(); @@ -254,7 +254,7 @@ template void lp_dual_simplex::fill_costs_and_bou template void lp_dual_simplex::fill_first_stage_solver_fields_for_row_slack_and_artificial(unsigned row, unsigned & slack_var, unsigned & artificial) { - lean_assert(row < this->row_count()); + lp_assert(row < this->row_count()); auto & constraint = this->m_constraints[this->m_core_solver_rows_to_external_rows[row]]; // we need to bring the program to the form Ax = b T rs = this->m_b[row]; @@ -335,7 +335,7 @@ template void lp_dual_simplex::find_maximal_solut this->flip_costs(); // do it for now, todo ( remove the flipping) - this->cleanup(); + this->clpup(); if (this->m_status == INFEASIBLE) { return; } diff --git a/src/util/lp/lp_dual_simplex_instances.cpp b/src/util/lp/lp_dual_simplex_instances.cpp index 6610814d8..a79a93748 100644 --- a/src/util/lp/lp_dual_simplex_instances.cpp +++ b/src/util/lp/lp_dual_simplex_instances.cpp @@ -3,7 +3,7 @@ Author: Lev Nachmanson */ #include "util/lp/lp_dual_simplex.hpp" -template lean::mpq lean::lp_dual_simplex::get_current_cost() const; -template void lean::lp_dual_simplex::find_maximal_solution(); -template double lean::lp_dual_simplex::get_current_cost() const; -template void lean::lp_dual_simplex::find_maximal_solution(); +template lp::mpq lp::lp_dual_simplex::get_current_cost() const; +template void lp::lp_dual_simplex::find_maximal_solution(); +template double lp::lp_dual_simplex::get_current_cost() const; +template void lp::lp_dual_simplex::find_maximal_solution(); diff --git a/src/util/lp/lp_primal_core_solver.h b/src/util/lp/lp_primal_core_solver.h index f77aae6eb..498288726 100644 --- a/src/util/lp/lp_primal_core_solver.h +++ b/src/util/lp/lp_primal_core_solver.h @@ -23,7 +23,7 @@ #include "util/lp/binary_heap_priority_queue.h" #include "util/lp/int_set.h" #include "util/lp/iterator_on_row.h" -namespace lean { +namespace lp { // This core solver solves (Ax=b, low_bound_values \leq x \leq upper_bound_values, maximize costs*x ) // The right side b is given implicitly by x and the basis @@ -70,7 +70,7 @@ public: // unsigned len = 100000000; // for (unsigned j : this->m_inf_set.m_index) { // int i = this->m_basis_heading[j]; - // lean_assert(i >= 0); + // lp_assert(i >= 0); // unsigned row_len = this->m_A.m_rows[i].size(); // if (row_len < len) { // choices.clear(); @@ -98,8 +98,8 @@ public: bool column_is_benefitial_for_entering_basis_on_sign_row_strategy(unsigned j, int sign) const { // sign = 1 means the x of the basis column of the row has to grow to become feasible, when the coeff before j is neg, or x - has to diminish when the coeff is pos // we have xbj = -aj * xj - lean_assert(this->m_basis_heading[j] < 0); - lean_assert(this->column_is_feasible(j)); + lp_assert(this->m_basis_heading[j] < 0); + lp_assert(this->column_is_feasible(j)); switch (this->m_column_types[j]) { case column_type::free_column: return true; case column_type::fixed: return false; @@ -117,13 +117,13 @@ public: return !this->x_is_at_upper_bound(j); } - lean_assert(false); // cannot be here + lp_assert(false); // cannot be here return false; } bool needs_to_grow(unsigned bj) const { - lean_assert(!this->column_is_feasible(bj)); + lp_assert(!this->column_is_feasible(bj)); switch(this->m_column_types[bj]) { case column_type::free_column: return false; @@ -134,12 +134,12 @@ public: default: return false; } - lean_assert(false); // unreachable + lp_assert(false); // unreachable return false; } int inf_sign_of_column(unsigned bj) const { - lean_assert(!this->column_is_feasible(bj)); + lp_assert(!this->column_is_feasible(bj)); switch(this->m_column_types[bj]) { case column_type::free_column: return 0; @@ -151,7 +151,7 @@ public: default: return -1; } - lean_assert(false); // unreachable + lp_assert(false); // unreachable return 0; } @@ -159,7 +159,7 @@ public: bool monoid_can_decrease(const row_cell & rc) const { unsigned j = rc.m_j; - lean_assert(this->column_is_feasible(j)); + lp_assert(this->column_is_feasible(j)); switch (this->m_column_types[j]) { case column_type::free_column: return true; @@ -186,13 +186,13 @@ public: default: return false; } - lean_assert(false); // unreachable + lp_assert(false); // unreachable return false; } bool monoid_can_increase(const row_cell & rc) const { unsigned j = rc.m_j; - lean_assert(this->column_is_feasible(j)); + lp_assert(this->column_is_feasible(j)); switch (this->m_column_types[j]) { case column_type::free_column: return true; @@ -219,7 +219,7 @@ public: default: return false; } - lean_assert(false); // unreachable + lp_assert(false); // unreachable return false; } @@ -329,24 +329,24 @@ public: } void limit_theta_on_basis_column_for_inf_case_m_neg_upper_bound(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m < 0 && this->m_column_types[j] == column_type::upper_bound); + lp_assert(m < 0 && this->m_column_types[j] == column_type::upper_bound); limit_inf_on_upper_bound_m_neg(m, this->m_x[j], this->m_upper_bounds[j], theta, unlimited); } void limit_theta_on_basis_column_for_inf_case_m_neg_low_bound(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m < 0 && this->m_column_types[j] == column_type::low_bound); + lp_assert(m < 0 && this->m_column_types[j] == column_type::low_bound); limit_inf_on_bound_m_neg(m, this->m_x[j], this->m_low_bounds[j], theta, unlimited); } void limit_theta_on_basis_column_for_inf_case_m_pos_low_bound(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m > 0 && this->m_column_types[j] == column_type::low_bound); + lp_assert(m > 0 && this->m_column_types[j] == column_type::low_bound); limit_inf_on_low_bound_m_pos(m, this->m_x[j], this->m_low_bounds[j], theta, unlimited); } void limit_theta_on_basis_column_for_inf_case_m_pos_upper_bound(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m > 0 && this->m_column_types[j] == column_type::upper_bound); + lp_assert(m > 0 && this->m_column_types[j] == column_type::upper_bound); limit_inf_on_bound_m_pos(m, this->m_x[j], this->m_upper_bounds[j], theta, unlimited); }; @@ -388,7 +388,7 @@ public: bool need_to_switch_costs() const { if (this->m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows) return false; - // lean_assert(calc_current_x_is_feasible() == current_x_is_feasible()); + // lp_assert(calc_current_x_is_feasible() == current_x_is_feasible()); return this->current_x_is_feasible() == this->m_using_infeas_costs; } @@ -443,7 +443,7 @@ public: if (j == -1) return -1; - lean_assert(!this->column_is_feasible(j)); + lp_assert(!this->column_is_feasible(j)); switch (this->m_column_types[j]) { case column_type::fixed: case column_type::upper_bound: @@ -459,7 +459,7 @@ public: new_val_for_leaving = this->m_low_bounds[j]; break; default: - lean_assert(false); + lp_assert(false); new_val_for_leaving = numeric_traits::zero(); // does not matter } return j; @@ -490,7 +490,7 @@ public: } X theta = (this->m_x[leaving] - new_val_for_leaving) / a_ent; advance_on_entering_and_leaving_tableau_rows(entering, leaving, theta ); - lean_assert(this->m_x[leaving] == new_val_for_leaving); + lp_assert(this->m_x[leaving] == new_val_for_leaving); if (this->current_x_is_feasible()) this->set_status(OPTIMAL); } @@ -507,13 +507,13 @@ public: void update_basis_and_x_with_comparison(unsigned entering, unsigned leaving, X delta); void decide_on_status_when_cannot_find_entering() { - lean_assert(!need_to_switch_costs()); + lp_assert(!need_to_switch_costs()); this->set_status(this->current_x_is_feasible()? OPTIMAL: INFEASIBLE); } // void limit_theta_on_basis_column_for_feas_case_m_neg(unsigned j, const T & m, X & theta) { - // lean_assert(m < 0); - // lean_assert(this->m_column_type[j] == low_bound || this->m_column_type[j] == boxed); + // lp_assert(m < 0); + // lp_assert(this->m_column_type[j] == low_bound || this->m_column_type[j] == boxed); // const X & eps = harris_eps_for_bound(this->m_low_bounds[j]); // if (this->above_bound(this->m_x[j], this->m_low_bounds[j])) { // theta = std::min((this->m_low_bounds[j] -this->m_x[j] - eps) / m, theta); @@ -522,7 +522,7 @@ public: // } void limit_theta_on_basis_column_for_feas_case_m_neg_no_check(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m < 0); + lp_assert(m < 0); const X& eps = harris_eps_for_bound(this->m_low_bounds[j]); limit_theta((this->m_low_bounds[j] - this->m_x[j] - eps) / m, theta, unlimited); if (theta < zero_of_type()) theta = zero_of_type(); @@ -530,7 +530,7 @@ public: bool limit_inf_on_bound_m_neg(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) { // x gets smaller - lean_assert(m < 0); + lp_assert(m < 0); if (numeric_traits::precise()) { if (this->below_bound(x, bound)) return false; if (this->above_bound(x, bound)) { @@ -554,7 +554,7 @@ public: bool limit_inf_on_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) { // x gets larger - lean_assert(m > 0); + lp_assert(m > 0); if (numeric_traits::precise()) { if (this->above_bound(x, bound)) return false; if (this->below_bound(x, bound)) { @@ -579,14 +579,14 @@ public: void limit_inf_on_low_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) { if (numeric_traits::precise()) { // x gets larger - lean_assert(m > 0); + lp_assert(m > 0); if (this->below_bound(x, bound)) { limit_theta((bound - x) / m, theta, unlimited); } } else { // x gets larger - lean_assert(m > 0); + lp_assert(m > 0); const X& eps = harris_eps_for_bound(bound); if (this->below_bound(x, bound)) { limit_theta((bound - x + eps) / m, theta, unlimited); @@ -596,7 +596,7 @@ public: void limit_inf_on_upper_bound_m_neg(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) { // x gets smaller - lean_assert(m < 0); + lp_assert(m < 0); const X& eps = harris_eps_for_bound(bound); if (this->above_bound(x, bound)) { limit_theta((bound - x - eps) / m, theta, unlimited); @@ -604,7 +604,7 @@ public: } void limit_theta_on_basis_column_for_inf_case_m_pos_boxed(unsigned j, const T & m, X & theta, bool & unlimited) { - // lean_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 & lbound = this->m_low_bounds[j]; @@ -624,7 +624,7 @@ public: } void limit_theta_on_basis_column_for_inf_case_m_neg_boxed(unsigned j, const T & m, X & theta, bool & unlimited) { - // lean_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 & ubound = this->m_upper_bounds[j]; if (this->above_bound(x, ubound)) { @@ -642,7 +642,7 @@ public: } } void limit_theta_on_basis_column_for_feas_case_m_pos(unsigned j, const T & m, X & theta, bool & unlimited) { - lean_assert(m > 0); + lp_assert(m > 0); const T& eps = harris_eps_for_bound(this->m_upper_bounds[j]); if (this->below_bound(this->m_x[j], this->m_upper_bounds[j])) { limit_theta((this->m_upper_bounds[j] - this->m_x[j] + eps) / m, theta, unlimited); @@ -654,7 +654,7 @@ public: } void limit_theta_on_basis_column_for_feas_case_m_pos_no_check(unsigned j, const T & m, X & theta, bool & unlimited ) { - lean_assert(m > 0); + lp_assert(m > 0); const X& eps = harris_eps_for_bound(this->m_upper_bounds[j]); limit_theta( (this->m_upper_bounds[j] - this->m_x[j] + eps) / m, theta, unlimited); if (theta < zero_of_type()) { @@ -720,7 +720,7 @@ public: break; default: - lean_unreachable(); + lp_unreachable(); } if (!unlimited && theta < zero_of_type()) { theta = zero_of_type(); @@ -803,7 +803,7 @@ public: case column_type::free_column: return 0; default: - lean_assert(false); + lp_assert(false); } return 0; } @@ -838,7 +838,7 @@ public: return -1; break; default: - lean_assert(false); + lp_assert(false); } return 0; @@ -864,7 +864,7 @@ public: // the delta is between the old and the new cost (old - new) void update_reduced_cost_for_basic_column_cost_change(const T & delta, unsigned j) { - lean_assert(this->m_basis_heading[j] >= 0); + lp_assert(this->m_basis_heading[j] >= 0); unsigned i = static_cast(this->m_basis_heading[j]); for (const row_cell & rc : this->m_A.m_rows[i]) { unsigned k = rc.m_j; @@ -943,7 +943,7 @@ public: upper_bound_values), m_beta(A.row_count()), m_converted_harris_eps(convert_struct::convert(this->m_settings.harris_feasibility_tolerance)) { - lean_assert(initial_x_is_correct()); + lp_assert(initial_x_is_correct()); m_low_bounds_dummy.resize(A.column_count(), zero_of_type()); m_enter_price_eps = numeric_traits::precise() ? numeric_traits::zero() : T(1e-5); #ifdef LEAN_DEBUG diff --git a/src/util/lp/lp_primal_core_solver.hpp b/src/util/lp/lp_primal_core_solver.hpp index 969d56812..d8d01f4b9 100644 --- a/src/util/lp/lp_primal_core_solver.hpp +++ b/src/util/lp/lp_primal_core_solver.hpp @@ -9,13 +9,13 @@ #include #include #include "util/lp/lp_primal_core_solver.h" -namespace lean { +namespace lp { // This core solver solves (Ax=b, low_bound_values \leq x \leq upper_bound_values, maximize costs*x ) // The right side b is given implicitly by x and the basis template void lp_primal_core_solver::sort_non_basis_rational() { - lean_assert(numeric_traits::precise()); + lp_assert(numeric_traits::precise()); if (this->m_settings.use_tableau()) { std::sort(this->m_nbasis.begin(), this->m_nbasis.end(), [this](unsigned a, unsigned b) { unsigned ca = this->m_A.number_of_non_zeroes_in_column(a); @@ -70,11 +70,11 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_on_breakpoin const T & d = this->m_d[j]; switch (this->m_column_types[j]) { case column_type::low_bound: - lean_assert(this->x_is_at_low_bound(j)); + lp_assert(this->x_is_at_low_bound(j)); ret = d < -m_epsilon_of_reduced_cost; break; case column_type::upper_bound: - lean_assert(this->x_is_at_upper_bound(j)); + lp_assert(this->x_is_at_upper_bound(j)); ret = d > m_epsilon_of_reduced_cost; break; case column_type::fixed: @@ -83,7 +83,7 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_on_breakpoin case column_type::boxed: { bool low_bound = this->x_is_at_low_bound(j); - lean_assert(low_bound || this->x_is_at_upper_bound(j)); + lp_assert(low_bound || this->x_is_at_upper_bound(j)); ret = (low_bound && d < -m_epsilon_of_reduced_cost) || ((!low_bound) && d > m_epsilon_of_reduced_cost); } break; @@ -91,7 +91,7 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_on_breakpoin ret = d > m_epsilon_of_reduced_cost || d < - m_epsilon_of_reduced_cost; break; default: - lean_unreachable(); + lp_unreachable(); ret = false; break; } @@ -127,14 +127,14 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_basis(unsign } break; default: - lean_unreachable(); + lp_unreachable(); break; } return false; } template bool lp_primal_core_solver::column_is_benefitial_for_entering_basis_precise(unsigned j) const { - lean_assert (numeric_traits::precise()); + lp_assert (numeric_traits::precise()); if (this->m_using_infeas_costs && this->m_settings.use_breakpoints_in_feasibility_search) return column_is_benefitial_for_entering_on_breakpoints(j); const T& dj = this->m_d[j]; @@ -167,7 +167,7 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_basis_precis } break; default: - lean_unreachable(); + lp_unreachable(); break; } return false; @@ -175,7 +175,7 @@ bool lp_primal_core_solver::column_is_benefitial_for_entering_basis_precis template int lp_primal_core_solver::choose_entering_column_presize(unsigned number_of_benefitial_columns_to_go_over) { // at this moment m_y = cB * B(-1) - lean_assert(numeric_traits::precise()); + lp_assert(numeric_traits::precise()); if (number_of_benefitial_columns_to_go_over == 0) return -1; if (this->m_basis_sort_counter == 0) { @@ -259,7 +259,7 @@ int lp_primal_core_solver::choose_entering_column(unsigned number_of_benef template int lp_primal_core_solver::advance_on_sorted_breakpoints(unsigned entering, X &t) { T slope_at_entering = this->m_d[entering]; breakpoint * last_bp = nullptr; - lean_assert(m_breakpoint_indices_queue.is_empty()==false); + lp_assert(m_breakpoint_indices_queue.is_empty()==false); while (m_breakpoint_indices_queue.is_empty() == false) { unsigned bi = m_breakpoint_indices_queue.dequeue(); breakpoint *b = &m_breakpoints[bi]; @@ -274,7 +274,7 @@ template int lp_primal_core_solver::advance_on_so } } } - lean_assert (last_bp != nullptr); + lp_assert (last_bp != nullptr); t = last_bp->m_delta; return last_bp->m_j; } @@ -282,13 +282,13 @@ template int lp_primal_core_solver::advance_on_so template int lp_primal_core_solver::find_leaving_and_t_with_breakpoints(unsigned entering, X & t){ - lean_assert(this->precise() == false); + lp_assert(this->precise() == false); fill_breakpoints_array(entering); return advance_on_sorted_breakpoints(entering, t); } template bool lp_primal_core_solver::get_harris_theta(X & theta) { - lean_assert(this->m_ed.is_OK()); + lp_assert(this->m_ed.is_OK()); bool unlimited = true; for (unsigned i : this->m_ed.m_index) { if (this->m_settings.abs_val_is_smaller_than_pivot_tolerance(this->m_ed[i])) continue; @@ -345,13 +345,13 @@ template bool lp_primal_core_solver::try_jump_to_ if (m_sign_of_entering_delta > 0) { t = this->m_upper_bounds[entering] - this->m_x[entering]; if (unlimited || t <= theta){ - lean_assert(t >= zero_of_type()); + lp_assert(t >= zero_of_type()); return true; } } else { // m_sign_of_entering_delta == -1 t = this->m_x[entering] - this->m_low_bounds[entering]; if (unlimited || t <= theta) { - lean_assert(t >= zero_of_type()); + lp_assert(t >= zero_of_type()); return true; } } @@ -360,7 +360,7 @@ template bool lp_primal_core_solver::try_jump_to_ if (m_sign_of_entering_delta > 0) { t = this->m_upper_bounds[entering] - this->m_x[entering]; if (unlimited || t <= theta){ - lean_assert(t >= zero_of_type()); + lp_assert(t >= zero_of_type()); return true; } } @@ -369,7 +369,7 @@ template bool lp_primal_core_solver::try_jump_to_ if (m_sign_of_entering_delta < 0) { t = this->m_x[entering] - this->m_low_bounds[entering]; if (unlimited || t <= theta) { - lean_assert(t >= zero_of_type()); + lp_assert(t >= zero_of_type()); return true; } } @@ -405,7 +405,7 @@ template int lp_primal_core_solver::find_leaving_ do { unsigned i = this->m_ed.m_index[k]; const T & ed = this->m_ed[i]; - lean_assert(!numeric_traits::is_zero(ed)); + lp_assert(!numeric_traits::is_zero(ed)); unsigned j = this->m_basis[i]; limit_theta_on_basis_column(j, - ed * m_sign_of_entering_delta, t, unlimited); if (!unlimited) { @@ -424,7 +424,7 @@ template int lp_primal_core_solver::find_leaving_ while (k != initial_k) { unsigned i = this->m_ed.m_index[k]; const T & ed = this->m_ed[i]; - lean_assert(!numeric_traits::is_zero(ed)); + lp_assert(!numeric_traits::is_zero(ed)); unsigned j = this->m_basis[i]; unlimited = true; limit_theta_on_basis_column(j, -ed * m_sign_of_entering_delta, ratio, unlimited); @@ -464,7 +464,7 @@ template int lp_primal_core_solver::find_leavi return find_leaving_and_t_with_breakpoints(entering, t); X theta; bool unlimited = get_harris_theta(theta); - lean_assert(unlimited || theta >= zero_of_type()); + lp_assert(unlimited || theta >= zero_of_type()); if (try_jump_to_another_bound_on_entering(entering, theta, t, unlimited)) return entering; if (unlimited) return -1; @@ -533,7 +533,7 @@ template X lp_primal_core_solver::get_max_boun template void lp_primal_core_solver::check_Ax_equal_b() { dense_matrix d(this->m_A); T * ls = d.apply_from_left_with_different_dims(this->m_x); - lean_assert(vectors_are_equal(ls, this->m_b, this->m_m())); + lp_assert(vectors_are_equal(ls, this->m_b, this->m_m())); delete [] ls; } template void lp_primal_core_solver::check_the_bounds() { @@ -543,8 +543,8 @@ template void lp_primal_core_solver::check_the } template void lp_primal_core_solver::check_bound(unsigned i) { - lean_assert (!(this->column_has_low_bound(i) && (numeric_traits::zero() > this->m_x[i]))); - lean_assert (!(this->column_has_upper_bound(i) && (this->m_upper_bounds[i] < this->m_x[i]))); + lp_assert (!(this->column_has_low_bound(i) && (numeric_traits::zero() > this->m_x[i]))); + lp_assert (!(this->column_has_upper_bound(i) && (this->m_upper_bounds[i] < this->m_x[i]))); } template void lp_primal_core_solver::check_correctness() { @@ -560,8 +560,8 @@ void lp_primal_core_solver::update_reduced_costs_from_pivot_row(unsigned e // the basis heading has changed already #ifdef LEAN_DEBUG auto & basis_heading = this->m_basis_heading; - lean_assert(basis_heading[entering] >= 0 && static_cast(basis_heading[entering]) < this->m_m()); - lean_assert(basis_heading[leaving] < 0); + lp_assert(basis_heading[entering] >= 0 && static_cast(basis_heading[entering]) < this->m_m()); + lp_assert(basis_heading[leaving] < 0); #endif T pivot = this->m_pivot_row[entering]; T dq = this->m_d[entering]/pivot; @@ -584,7 +584,7 @@ void lp_primal_core_solver::update_reduced_costs_from_pivot_row(unsigned e template int lp_primal_core_solver::refresh_reduced_cost_at_entering_and_check_that_it_is_off(unsigned entering) { if (numeric_traits::precise()) return 0; T reduced_at_entering_was = this->m_d[entering]; // can benefit from going over non-zeros of m_ed - lean_assert(abs(reduced_at_entering_was) > m_epsilon_of_reduced_cost); + lp_assert(abs(reduced_at_entering_was) > m_epsilon_of_reduced_cost); T refreshed_cost = this->m_costs[entering]; unsigned i = this->m_m(); while (i--) refreshed_cost -= this->m_costs[this->m_basis[i]] * this->m_ed[i]; @@ -619,7 +619,7 @@ template void lp_primal_core_solver::backup_an m_costs_backup = this->m_costs; } else { T cost_max = std::max(max_abs_in_vector(this->m_costs), T(1)); - lean_assert(m_costs_backup.size() == 0); + lp_assert(m_costs_backup.size() == 0); for (unsigned j = 0; j < this->m_costs.size(); j++) m_costs_backup.push_back(this->m_costs[j] /= cost_max); } @@ -649,16 +649,16 @@ template void lp_primal_core_solver::init_run( template void lp_primal_core_solver::calc_working_vector_beta_for_column_norms(){ - lean_assert(numeric_traits::precise() == false); - lean_assert(this->m_ed.is_OK()); - lean_assert(m_beta.is_OK()); + lp_assert(numeric_traits::precise() == false); + lp_assert(this->m_ed.is_OK()); + lp_assert(m_beta.is_OK()); m_beta = this->m_ed; this->m_factorization->solve_yB_with_error_check_indexed(m_beta, this->m_basis_heading, this->m_basis, this->m_settings); } template void lp_primal_core_solver::advance_on_entering_equal_leaving(int entering, X & t) { - lean_assert(!this->A_mult_x_is_off() ); + lp_assert(!this->A_mult_x_is_off() ); this->update_x(entering, t * m_sign_of_entering_delta); if (this->A_mult_x_is_off_on_index(this->m_ed.m_index) && !this->find_x_by_solving()) { this->init_lu(); @@ -670,7 +670,7 @@ void lp_primal_core_solver::advance_on_entering_equal_leaving(int entering } } if (this->m_using_infeas_costs) { - lean_assert(is_zero(this->m_costs[entering])); + lp_assert(is_zero(this->m_costs[entering])); init_infeasibility_costs_for_changed_basis_only(); } if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible()) @@ -683,10 +683,10 @@ void lp_primal_core_solver::advance_on_entering_equal_leaving(int entering } template void lp_primal_core_solver::advance_on_entering_and_leaving(int entering, int leaving, X & t) { - lean_assert(entering >= 0 && m_non_basis_list.back() == static_cast(entering)); - lean_assert(this->m_using_infeas_costs || t >= zero_of_type()); - lean_assert(leaving >= 0 && entering >= 0); - lean_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes + lp_assert(entering >= 0 && m_non_basis_list.back() == static_cast(entering)); + lp_assert(this->m_using_infeas_costs || t >= zero_of_type()); + lp_assert(leaving >= 0 && entering >= 0); + lp_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes if (entering == leaving) { advance_on_entering_equal_leaving(entering, t); return; @@ -702,7 +702,7 @@ template void lp_primal_core_solver::advance_on_en this->iters_with_no_cost_growing()++; return; } else { - lean_assert(pivot_compare_result == 1); + lp_assert(pivot_compare_result == 1); this->init_lu(); if (this->m_factorization == nullptr || this->m_factorization->get_status() != LU_status::OK) { this->set_status(UNSTABLE); @@ -746,7 +746,7 @@ template void lp_primal_core_solver::advance_on_en } else { update_reduced_costs_from_pivot_row(entering, leaving); } - lean_assert(!need_to_switch_costs()); + lp_assert(!need_to_switch_costs()); std::list::iterator it = m_non_basis_list.end(); it--; * it = static_cast(leaving); @@ -754,8 +754,8 @@ template void lp_primal_core_solver::advance_on_en template void lp_primal_core_solver::advance_on_entering_precise(int entering) { - lean_assert(numeric_traits::precise()); - lean_assert(entering > -1); + lp_assert(numeric_traits::precise()); + lp_assert(entering > -1); this->solve_Bd(entering); X t; int leaving = find_leaving_and_t_precise(entering, t); @@ -771,7 +771,7 @@ template void lp_primal_core_solver::advance_on_e advance_on_entering_precise(entering); return; } - lean_assert(entering > -1); + lp_assert(entering > -1); this->solve_Bd(entering); int refresh_result = refresh_reduced_cost_at_entering_and_check_that_it_is_off(entering); if (refresh_result) { @@ -791,7 +791,7 @@ template void lp_primal_core_solver::advance_on_e int leaving = find_leaving_and_t(entering, t); if (leaving == -1){ if (!this->current_x_is_feasible()) { - lean_assert(!numeric_traits::precise()); // we cannot have unbounded with inf costs + lp_assert(!numeric_traits::precise()); // we cannot have unbounded with inf costs // if (m_look_for_feasible_solution_only) { // this->m_status = INFEASIBLE; @@ -865,7 +865,7 @@ template unsigned lp_primal_core_solver::solve() return this->total_iterations(); } one_iteration(); - lean_assert(!this->m_using_infeas_costs || this->costs_on_nbasis_are_zeros()); + lp_assert(!this->m_using_infeas_costs || this->costs_on_nbasis_are_zeros()); switch (this->get_status()) { case OPTIMAL: // double check that we are at optimum case INFEASIBLE: @@ -914,7 +914,7 @@ template unsigned lp_primal_core_solver::solve() break; case UNSTABLE: - lean_assert(! (numeric_traits::precise())); + lp_assert(! (numeric_traits::precise())); this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { this->set_status(FLOATING_POINT_ERROR); @@ -940,7 +940,7 @@ template unsigned lp_primal_core_solver::solve() && !(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only)); - lean_assert(this->get_status() == FLOATING_POINT_ERROR + lp_assert(this->get_status() == FLOATING_POINT_ERROR || this->current_x_is_feasible() == false || @@ -957,7 +957,7 @@ template void lp_primal_core_solver::delete_fa // according to Swietanowski, " A new steepest edge approximation for the simplex method for linear programming" template void lp_primal_core_solver::init_column_norms() { - lean_assert(numeric_traits::precise() == false); + lp_assert(numeric_traits::precise() == false); for (unsigned j = 0; j < this->m_n(); j++) { this->m_column_norms[j] = T(static_cast(this->m_A.m_columns[j].size() + 1)) @@ -967,7 +967,7 @@ template void lp_primal_core_solver::init_column_ // debug only template T lp_primal_core_solver::calculate_column_norm_exactly(unsigned j) { - lean_assert(numeric_traits::precise() == false); + lp_assert(numeric_traits::precise() == false); indexed_vector w(this->m_m()); this->m_A.copy_column_to_vector(j, w); vector d(this->m_m()); @@ -979,8 +979,8 @@ template T lp_primal_core_solver::calculate_colum } template void lp_primal_core_solver::update_or_init_column_norms(unsigned entering, unsigned leaving) { - lean_assert(numeric_traits::precise() == false); - lean_assert(m_column_norm_update_counter <= this->m_settings.column_norms_update_frequency); + lp_assert(numeric_traits::precise() == false); + lp_assert(m_column_norm_update_counter <= this->m_settings.column_norms_update_frequency); if (m_column_norm_update_counter == this->m_settings.column_norms_update_frequency) { m_column_norm_update_counter = 0; init_column_norms(); @@ -992,7 +992,7 @@ template void lp_primal_core_solver::update_or // following Swietanowski - A new steepest ... template void lp_primal_core_solver::update_column_norms(unsigned entering, unsigned leaving) { - lean_assert(numeric_traits::precise() == false); + lp_assert(numeric_traits::precise() == false); T pivot = this->m_pivot_row[entering]; T g_ent = calculate_norm_of_entering_exactly() / pivot / pivot; if (!numeric_traits::precise()) { @@ -1027,7 +1027,7 @@ template T lp_primal_core_solver::calculate_no // calling it stage1 is too cryptic template void lp_primal_core_solver::find_feasible_solution() { this->m_look_for_feasible_solution_only = true; - lean_assert(this->non_basic_columns_are_set_correctly()); + lp_assert(this->non_basic_columns_are_set_correctly()); this->set_status(UNKNOWN); solve(); } @@ -1095,8 +1095,8 @@ void lp_primal_core_solver::init_infeasibility_costs_for_changed_basis_onl template void lp_primal_core_solver::init_infeasibility_costs() { - lean_assert(this->m_x.size() >= this->m_n()); - lean_assert(this->m_column_types.size() >= this->m_n()); + lp_assert(this->m_x.size() >= this->m_n()); + lp_assert(this->m_column_types.size() >= this->m_n()); for (unsigned j = this->m_n(); j--;) init_infeasibility_cost_for_column(j); this->m_using_infeas_costs = true; @@ -1138,7 +1138,7 @@ lp_primal_core_solver::get_infeasibility_cost_for_column(unsigned j) const ret = numeric_traits::zero(); break; default: - lean_assert(false); + lp_assert(false); ret = numeric_traits::zero(); // does not matter break; } @@ -1192,7 +1192,7 @@ lp_primal_core_solver::init_infeasibility_cost_for_column(unsigned j) { this->m_costs[j] = numeric_traits::zero(); break; default: - lean_assert(false); + lp_assert(false); break; } @@ -1223,7 +1223,7 @@ template void lp_primal_core_solver::print_column case column_type::free_column: out << "( _" << this->m_x[j] << "_)" << std::endl; default: - lean_unreachable(); + lp_unreachable(); } } @@ -1262,7 +1262,7 @@ template std::string lp_primal_core_solver::break case upper_break: return "upper_break"; case fixed_break: return "fixed_break"; default: - lean_assert(false); + lp_assert(false); break; } return "type is not found"; @@ -1275,7 +1275,7 @@ template void lp_primal_core_solver::print_breakp template void lp_primal_core_solver::init_reduced_costs() { - lean_assert(!this->use_tableau()); + lp_assert(!this->use_tableau()); if (this->current_x_is_infeasible() && !this->m_using_infeas_costs) { init_infeasibility_costs(); } else if (this->current_x_is_feasible() && this->m_using_infeas_costs) { @@ -1290,12 +1290,12 @@ void lp_primal_core_solver::init_reduced_costs() { template void lp_primal_core_solver::change_slope_on_breakpoint(unsigned entering, breakpoint * b, T & slope_at_entering) { if (b->m_j == entering) { - lean_assert(b->m_type != fixed_break && (!is_zero(b->m_delta))); + lp_assert(b->m_type != fixed_break && (!is_zero(b->m_delta))); slope_at_entering += m_sign_of_entering_delta; return; } - lean_assert(this->m_basis_heading[b->m_j] >= 0); + lp_assert(this->m_basis_heading[b->m_j] >= 0); unsigned i_row = this->m_basis_heading[b->m_j]; const T & d = - this->m_ed[i_row]; if (numeric_traits::is_zero(d)) return; @@ -1314,13 +1314,13 @@ template void lp_primal_core_solver::change_sl slope_at_entering += delta; break; default: - lean_assert(false); + lp_assert(false); } } template void lp_primal_core_solver::try_add_breakpoint_in_row(unsigned i) { - lean_assert(i < this->m_m()); + lp_assert(i < this->m_m()); const T & d = this->m_ed[i]; // the coefficient before m_entering in the i-th row if (d == 0) return; // the change of x[m_entering] will not change the corresponding basis x unsigned j = this->m_basis[i]; @@ -1342,7 +1342,7 @@ template void lp_primal_core_solver::try_add_b case column_type::free_column: break; default: - lean_assert(false); + lp_assert(false); break; } } @@ -1366,7 +1366,7 @@ template void lp_primal_core_solver::print_bound_ out << "inf, inf" << std::endl; break; default: - lean_assert(false); + lp_assert(false); break; } } diff --git a/src/util/lp/lp_primal_core_solver_instances.cpp b/src/util/lp/lp_primal_core_solver_instances.cpp index ca231fd34..8e5890bf5 100644 --- a/src/util/lp/lp_primal_core_solver_instances.cpp +++ b/src/util/lp/lp_primal_core_solver_instances.cpp @@ -10,18 +10,18 @@ #include "util/lp/lar_solver.h" #include "util/lp/lp_primal_core_solver.hpp" #include "util/lp/lp_primal_core_solver_tableau.hpp" -namespace lean { +namespace lp { template void lp_primal_core_solver::find_feasible_solution(); -template void lean::lp_primal_core_solver >::find_feasible_solution(); +template void lp::lp_primal_core_solver >::find_feasible_solution(); template unsigned lp_primal_core_solver::solve(); template unsigned lp_primal_core_solver::solve_with_tableau(); template unsigned lp_primal_core_solver::solve(); template unsigned lp_primal_core_solver >::solve(); -template void lean::lp_primal_core_solver::clear_breakpoints(); -template bool lean::lp_primal_core_solver::update_basis_and_x_tableau(int, int, lean::mpq const&); -template bool lean::lp_primal_core_solver::update_basis_and_x_tableau(int, int, double const&); -template bool lean::lp_primal_core_solver >::update_basis_and_x_tableau(int, int, lean::numeric_pair const&); +template void lp::lp_primal_core_solver::clear_breakpoints(); +template bool lp::lp_primal_core_solver::update_basis_and_x_tableau(int, int, lp::mpq const&); +template bool lp::lp_primal_core_solver::update_basis_and_x_tableau(int, int, double const&); +template bool lp::lp_primal_core_solver >::update_basis_and_x_tableau(int, int, lp::numeric_pair const&); } diff --git a/src/util/lp/lp_primal_core_solver_tableau.hpp b/src/util/lp/lp_primal_core_solver_tableau.hpp index 0c09c22c9..d2ce78472 100644 --- a/src/util/lp/lp_primal_core_solver_tableau.hpp +++ b/src/util/lp/lp_primal_core_solver_tableau.hpp @@ -4,7 +4,7 @@ */ // this is a part of lp_primal_core_solver that deals with the tableau #include "util/lp/lp_primal_core_solver.h" -namespace lean { +namespace lp { template void lp_primal_core_solver::one_iteration_tableau() { int entering = choose_entering_column_tableau(); if (entering == -1) { @@ -13,7 +13,7 @@ template void lp_primal_core_solver::one_iteratio else { advance_on_entering_tableau(entering); } - lean_assert(this->inf_set_is_correct()); + lp_assert(this->inf_set_is_correct()); } template void lp_primal_core_solver::advance_on_entering_tableau(int entering) { @@ -37,7 +37,7 @@ template int lp_primal_core_solver::choose_enteri //this moment m_y = cB * B(-1) unsigned number_of_benefitial_columns_to_go_over = get_number_of_non_basic_column_to_try_for_enter(); - lean_assert(numeric_traits::precise()); + lp_assert(numeric_traits::precise()); if (number_of_benefitial_columns_to_go_over == 0) return -1; if (this->m_basis_sort_counter == 0) { @@ -149,7 +149,7 @@ unsigned lp_primal_core_solver::solve_with_tableau() { break; case UNSTABLE: - lean_assert(! (numeric_traits::precise())); + lp_assert(! (numeric_traits::precise())); this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { this->set_status(FLOATING_POINT_ERROR); @@ -175,7 +175,7 @@ unsigned lp_primal_core_solver::solve_with_tableau() { && !(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only)); - lean_assert(this->get_status() == FLOATING_POINT_ERROR + lp_assert(this->get_status() == FLOATING_POINT_ERROR || this->current_x_is_feasible() == false || @@ -184,13 +184,13 @@ unsigned lp_primal_core_solver::solve_with_tableau() { } template void lp_primal_core_solver::advance_on_entering_and_leaving_tableau(int entering, int leaving, X & t) { - lean_assert(this->A_mult_x_is_off() == false); - lean_assert(leaving >= 0 && entering >= 0); - lean_assert((this->m_settings.simplex_strategy() == + lp_assert(this->A_mult_x_is_off() == false); + lp_assert(leaving >= 0 && entering >= 0); + lp_assert((this->m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows) || m_non_basis_list.back() == static_cast(entering)); - lean_assert(this->m_using_infeas_costs || !is_neg(t)); - lean_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes + lp_assert(this->m_using_infeas_costs || !is_neg(t)); + lp_assert(entering != leaving || !is_zero(t)); // otherwise nothing changes if (entering == leaving) { advance_on_entering_equal_leaving_tableau(entering, t); return; @@ -201,7 +201,7 @@ template void lp_primal_core_solver::advance_on_en t = -t; } this->update_basis_and_x_tableau(entering, leaving, t); - lean_assert(this->A_mult_x_is_off() == false); + lp_assert(this->A_mult_x_is_off() == false); this->iters_with_no_cost_growing() = 0; } else { this->pivot_column_tableau(entering, this->m_basis_heading[leaving]); @@ -216,7 +216,7 @@ template void lp_primal_core_solver::advance_on_en this->init_reduced_costs_tableau(); } - lean_assert(!need_to_switch_costs()); + lp_assert(!need_to_switch_costs()); std::list::iterator it = m_non_basis_list.end(); it--; * it = static_cast(leaving); @@ -225,7 +225,7 @@ template void lp_primal_core_solver::advance_on_en template void lp_primal_core_solver::advance_on_entering_equal_leaving_tableau(int entering, X & t) { - lean_assert(!this->A_mult_x_is_off() ); + lp_assert(!this->A_mult_x_is_off() ); this->update_x_tableau(entering, t * m_sign_of_entering_delta); if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible()) return; @@ -246,7 +246,7 @@ template int lp_primal_core_solver::find_leaving_ const column_cell & c = col[k]; unsigned i = c.m_i; const T & ed = this->m_A.get_val(c); - lean_assert(!numeric_traits::is_zero(ed)); + lp_assert(!numeric_traits::is_zero(ed)); unsigned j = this->m_basis[i]; limit_theta_on_basis_column(j, - ed * m_sign_of_entering_delta, t, unlimited); if (!unlimited) { @@ -265,7 +265,7 @@ template int lp_primal_core_solver::find_leaving_ const column_cell & c = col[k]; unsigned i = c.m_i; const T & ed = this->m_A.get_val(c); - lean_assert(!numeric_traits::is_zero(ed)); + lp_assert(!numeric_traits::is_zero(ed)); unsigned j = this->m_basis[i]; unlimited = true; limit_theta_on_basis_column(j, -ed * m_sign_of_entering_delta, ratio, unlimited); @@ -298,12 +298,12 @@ template int lp_primal_core_solver::find_leaving_ } template void lp_primal_core_solver::init_run_tableau() { // print_matrix(&(this->m_A), std::cout); - lean_assert(this->A_mult_x_is_off() == false); - lean_assert(basis_columns_are_set_correctly()); + lp_assert(this->A_mult_x_is_off() == false); + lp_assert(basis_columns_are_set_correctly()); this->m_basis_sort_counter = 0; // to initiate the sort of the basis this->set_total_iterations(0); this->iters_with_no_cost_growing() = 0; - lean_assert(this->inf_set_is_correct()); + lp_assert(this->inf_set_is_correct()); if (this->current_x_is_feasible() && this->m_look_for_feasible_solution_only) return; if (this->m_settings.backup_costs) @@ -317,13 +317,13 @@ template void lp_primal_core_solver::init_run_tab } if (this->m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows) init_tableau_rows(); - lean_assert(this->reduced_costs_are_correct_tableau()); - lean_assert(!this->need_to_pivot_to_basis_tableau()); + lp_assert(this->reduced_costs_are_correct_tableau()); + lp_assert(!this->need_to_pivot_to_basis_tableau()); } template bool lp_primal_core_solver:: update_basis_and_x_tableau(int entering, int leaving, X const & tt) { - lean_assert(this->use_tableau()); + lp_assert(this->use_tableau()); update_x_tableau(entering, tt); this->pivot_column_tableau(entering, this->m_basis_heading[leaving]); this->change_basis(entering, leaving); @@ -340,8 +340,8 @@ update_x_tableau(unsigned entering, const X& delta) { } } else { // m_using_infeas_costs == true this->m_x[entering] += delta; - lean_assert(this->column_is_feasible(entering)); - lean_assert(this->m_costs[entering] == zero_of_type()); + lp_assert(this->column_is_feasible(entering)); + lp_assert(this->m_costs[entering] == zero_of_type()); // m_d[entering] can change because of the cost change for basic columns. for (const auto & c : this->m_A.m_columns[entering]) { unsigned i = c.m_i; @@ -354,13 +354,13 @@ update_x_tableau(unsigned entering, const X& delta) { this->m_inf_set.insert(j); } } - lean_assert(this->A_mult_x_is_off() == false); + lp_assert(this->A_mult_x_is_off() == false); } template void lp_primal_core_solver:: update_inf_cost_for_column_tableau(unsigned j) { - lean_assert(this->m_settings.simplex_strategy() != simplex_strategy_enum::tableau_rows); - lean_assert(this->m_using_infeas_costs); + lp_assert(this->m_settings.simplex_strategy() != simplex_strategy_enum::tableau_rows); + lp_assert(this->m_using_infeas_costs); T new_cost = get_infeasibility_cost_for_column(j); T delta = this->m_costs[j] - new_cost; if (is_zero(delta)) diff --git a/src/util/lp/lp_primal_simplex.h b/src/util/lp/lp_primal_simplex.h index 715d76408..b55fecdcd 100644 --- a/src/util/lp/lp_primal_simplex.h +++ b/src/util/lp/lp_primal_simplex.h @@ -12,7 +12,7 @@ #include "util/lp/lp_primal_core_solver.h" #include "util/lp/lp_solver.h" #include "util/lp/iterator_on_row.h" -namespace lean { +namespace lp { template class lp_primal_simplex: public lp_solver { lp_primal_core_solver * m_core_solver; diff --git a/src/util/lp/lp_primal_simplex.hpp b/src/util/lp/lp_primal_simplex.hpp index b6b6006e5..76ed5684c 100644 --- a/src/util/lp/lp_primal_simplex.hpp +++ b/src/util/lp/lp_primal_simplex.hpp @@ -6,7 +6,7 @@ #include "util/vector.h" #include "util/lp/lp_primal_simplex.h" -namespace lean { +namespace lp { template void lp_primal_simplex::fill_costs_and_x_for_first_stage_solver(unsigned original_number_of_columns) { unsigned slack_var = original_number_of_columns; unsigned artificial = original_number_of_columns + this->m_slacks; @@ -61,7 +61,7 @@ template void lp_primal_simplex::fill_costs_and_x int row, unsigned & slack_var, unsigned & artificial) { - lean_assert(row >= 0 && row < this->row_count()); + lp_assert(row >= 0 && row < this->row_count()); auto & constraint = this->m_constraints[this->m_core_solver_rows_to_external_rows[row]]; // we need to bring the program to the form Ax = b T rs = this->m_b[row]; @@ -86,7 +86,7 @@ template void lp_primal_simplex::fill_costs_and_x (*this->m_A)(row, slack_var) = - numeric_traits::one(); if (rs > 0) { - lean_assert(numeric_traits::is_zero(this->m_x[slack_var])); + lp_assert(numeric_traits::is_zero(this->m_x[slack_var])); // adding one artificial this->m_column_types[artificial] = column_type::low_bound; (*this->m_A)(row, artificial) = numeric_traits::one(); @@ -108,7 +108,7 @@ template void lp_primal_simplex::fill_costs_and_x if (rs < 0) { // adding one artificial - lean_assert(numeric_traits::is_zero(this->m_x[slack_var])); + lp_assert(numeric_traits::is_zero(this->m_x[slack_var])); this->m_column_types[artificial] = column_type::low_bound; (*this->m_A)(row, artificial) = - numeric_traits::one(); this->m_costs[artificial] = artificial_cost; @@ -157,7 +157,7 @@ template void lp_primal_simplex::find_maximal_sol return; } - this->cleanup(); + this->clpup(); this->fill_matrix_A_and_init_right_side(); if (this->m_status == lp_status::INFEASIBLE) { return; @@ -177,12 +177,12 @@ template void lp_primal_simplex::fill_A_x_and_bas } template void lp_primal_simplex::fill_A_x_and_basis_for_stage_one_total_inf_for_row(unsigned row) { - lean_assert(row < this->row_count()); + lp_assert(row < this->row_count()); auto ext_row_it = this->m_core_solver_rows_to_external_rows.find(row); - lean_assert(ext_row_it != this->m_core_solver_rows_to_external_rows.end()); + lp_assert(ext_row_it != this->m_core_solver_rows_to_external_rows.end()); unsigned ext_row = ext_row_it->second; auto constr_it = this->m_constraints.find(ext_row); - lean_assert(constr_it != this->m_constraints.end()); + lp_assert(constr_it != this->m_constraints.end()); auto & constraint = constr_it->second; unsigned j = this->m_A->column_count(); // j is a slack variable this->m_A->add_column(); @@ -209,7 +209,7 @@ template void lp_primal_simplex::fill_A_x_and_bas this->m_upper_bounds[j] = m_low_bounds[j] = zero_of_type(); break; default: - lean_unreachable(); + lp_unreachable(); } } @@ -281,10 +281,10 @@ template T lp_primal_simplex::get_row_value(unsig T ret = numeric_traits::zero(); for (auto & pair : it->second) { auto cit = this->m_map_from_var_index_to_column_info.find(pair.first); - lean_assert(cit != this->m_map_from_var_index_to_column_info.end()); + lp_assert(cit != this->m_map_from_var_index_to_column_info.end()); column_info * ci = cit->second; auto sol_it = solution.find(ci->get_name()); - lean_assert(sol_it != solution.end()); + lp_assert(sol_it != solution.end()); T column_val = sol_it->second; if (out != nullptr) { (*out) << pair.second << "(" << ci->get_name() << "=" << column_val << ") "; @@ -329,7 +329,7 @@ template bool lp_primal_simplex::row_constraint_h } return true;; } - lean_unreachable(); + lp_unreachable(); return false; // it is unreachable } diff --git a/src/util/lp/lp_primal_simplex_instances.cpp b/src/util/lp/lp_primal_simplex_instances.cpp index 37b639489..249be218c 100644 --- a/src/util/lp/lp_primal_simplex_instances.cpp +++ b/src/util/lp/lp_primal_simplex_instances.cpp @@ -8,13 +8,13 @@ #include "util/vector.h" #include #include "util/lp/lp_primal_simplex.hpp" -template bool lean::lp_primal_simplex::bounds_hold(std::unordered_map, std::equal_to, std::allocator > > const&); -template bool lean::lp_primal_simplex::row_constraints_hold(std::unordered_map, std::equal_to, std::allocator > > const&); -template double lean::lp_primal_simplex::get_current_cost() const; -template double lean::lp_primal_simplex::get_column_value(unsigned int) const; -template lean::lp_primal_simplex::~lp_primal_simplex(); -template lean::lp_primal_simplex::~lp_primal_simplex(); -template lean::mpq lean::lp_primal_simplex::get_current_cost() const; -template lean::mpq lean::lp_primal_simplex::get_column_value(unsigned int) const; -template void lean::lp_primal_simplex::find_maximal_solution(); -template void lean::lp_primal_simplex::find_maximal_solution(); +template bool lp::lp_primal_simplex::bounds_hold(std::unordered_map, std::equal_to, std::allocator > > const&); +template bool lp::lp_primal_simplex::row_constraints_hold(std::unordered_map, std::equal_to, std::allocator > > const&); +template double lp::lp_primal_simplex::get_current_cost() const; +template double lp::lp_primal_simplex::get_column_value(unsigned int) const; +template lp::lp_primal_simplex::~lp_primal_simplex(); +template lp::lp_primal_simplex::~lp_primal_simplex(); +template lp::mpq lp::lp_primal_simplex::get_current_cost() const; +template lp::mpq lp::lp_primal_simplex::get_column_value(unsigned int) const; +template void lp::lp_primal_simplex::find_maximal_solution(); +template void lp::lp_primal_simplex::find_maximal_solution(); diff --git a/src/util/lp/lp_settings.h b/src/util/lp/lp_settings.h index 736e4cda4..3b6b44614 100644 --- a/src/util/lp/lp_settings.h +++ b/src/util/lp/lp_settings.h @@ -12,7 +12,7 @@ #include "util/lp/lp_utils.h" #include "util/stopwatch.h" -namespace lean { +namespace lp { typedef unsigned var_index; typedef unsigned constraint_index; typedef unsigned row_index; @@ -374,7 +374,7 @@ inline void print_blanks(int n, std::ostream & out) { // after a push of the last element we ensure that the vector increases // we also suppose that before the last push the vector was increasing inline void ensure_increasing(vector & v) { - lean_assert(v.size() > 0); + lp_assert(v.size() > 0); unsigned j = v.size() - 1; for (; j > 0; j-- ) if (v[j] <= v[j - 1]) { diff --git a/src/util/lp/lp_settings.hpp b/src/util/lp/lp_settings.hpp index b27d837e0..b07395222 100644 --- a/src/util/lp/lp_settings.hpp +++ b/src/util/lp/lp_settings.hpp @@ -6,7 +6,7 @@ #include #include "util/vector.h" #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { std::string column_type_to_string(column_type t) { switch (t) { case column_type::fixed: return "fixed"; @@ -14,7 +14,7 @@ std::string column_type_to_string(column_type t) { case column_type::low_bound: return "low_bound"; case column_type::upper_bound: return "upper_bound"; case column_type::free_column: return "free_column"; - default: lean_unreachable(); + default: lp_unreachable(); } return "unknown"; // it is unreachable } @@ -34,7 +34,7 @@ const char* lp_status_to_string(lp_status status) { case EMPTY: return "EMPTY"; case UNSTABLE: return "UNSTABLE"; default: - lean_unreachable(); + lp_unreachable(); } return "UNKNOWN"; // it is unreachable } @@ -49,7 +49,7 @@ lp_status lp_status_from_string(std::string status) { if (status == "TIME_EXHAUSTED") return lp_status::TIME_EXHAUSTED; if (status == "ITERATIONS_EXHAUSTED") return lp_status::ITERATIONS_EXHAUSTED; if (status == "EMPTY") return lp_status::EMPTY; - lean_unreachable(); + lp_unreachable(); return lp_status::UNKNOWN; // it is unreachable } diff --git a/src/util/lp/lp_settings_instances.cpp b/src/util/lp/lp_settings_instances.cpp index ac2ed4b51..9e809e7c6 100644 --- a/src/util/lp/lp_settings_instances.cpp +++ b/src/util/lp/lp_settings_instances.cpp @@ -5,6 +5,6 @@ #include #include "util/vector.h" #include "util/lp/lp_settings.hpp" -template bool lean::vectors_are_equal(vector const&, vector const&); -template bool lean::vectors_are_equal(vector const&, vector const&); +template bool lp::vectors_are_equal(vector const&, vector const&); +template bool lp::vectors_are_equal(vector const&, vector const&); diff --git a/src/util/lp/lp_solver.h b/src/util/lp/lp_solver.h index 1bfe7dcdc..984e818e1 100644 --- a/src/util/lp/lp_solver.h +++ b/src/util/lp/lp_solver.h @@ -15,7 +15,7 @@ #include "util/lp/scaler.h" #include "util/lp/linear_combination_iterator.h" #include "util/lp/bound_analyzer_on_row.h" -namespace lean { +namespace lp { enum lp_relation { Less_or_equal, Equal, @@ -205,7 +205,7 @@ protected: unsigned try_to_remove_some_rows(); - void cleanup(); + void clpup(); void map_external_rows_to_core_solver_rows(); diff --git a/src/util/lp/lp_solver.hpp b/src/util/lp/lp_solver.hpp index 135616a69..46674cf5e 100644 --- a/src/util/lp/lp_solver.hpp +++ b/src/util/lp/lp_solver.hpp @@ -6,7 +6,7 @@ #include #include "util/vector.h" #include "util/lp/lp_solver.h" -namespace lean { +namespace lp { template column_info * lp_solver::get_or_create_column_info(unsigned column) { auto it = m_map_from_var_index_to_column_info.find(column); return (it == m_map_from_var_index_to_column_info.end())? (m_map_from_var_index_to_column_info[column] = new column_info(static_cast(-1))) : it->second; @@ -32,7 +32,7 @@ template T lp_solver::get_column_cost_value(unsig return ci->get_cost() * get_column_value(j); } template void lp_solver::add_constraint(lp_relation relation, T right_side, unsigned row_index) { - lean_assert(m_constraints.find(row_index) == m_constraints.end()); + lp_assert(m_constraints.find(row_index) == m_constraints.end()); lp_constraint cs(right_side, relation); m_constraints[row_index] = cs; } @@ -158,10 +158,10 @@ template void lp_solver::pin_vars_on_row_with_sig column_info * ci = m_map_from_var_index_to_column_info[j]; T a = t.second; if (a * sign > numeric_traits::zero()) { - lean_assert(ci->upper_bound_is_set()); + lp_assert(ci->upper_bound_is_set()); ci->set_fixed_value(ci->get_upper_bound()); } else { - lean_assert(ci->low_bound_is_set()); + lp_assert(ci->low_bound_is_set()); ci->set_fixed_value(ci->get_low_bound()); } } @@ -328,7 +328,7 @@ template bool lp_solver::row_is_obsolete(std:: case lp_relation::Less_or_equal: return row_le_is_obsolete(row, row_index); } - lean_unreachable(); + lp_unreachable(); return false; // it is unreachable } @@ -343,7 +343,7 @@ template void lp_solver::remove_fixed_or_zero_col vector removed; for (auto & col : row) { unsigned j = col.first; - lean_assert(m_map_from_var_index_to_column_info.find(j) != m_map_from_var_index_to_column_info.end()); + lp_assert(m_map_from_var_index_to_column_info.find(j) != m_map_from_var_index_to_column_info.end()); column_info * ci = m_map_from_var_index_to_column_info[j]; if (ci->is_fixed()) { removed.push_back(j); @@ -381,7 +381,7 @@ template unsigned lp_solver::try_to_remove_some_r return static_cast(rows_to_delete.size()); } -template void lp_solver::cleanup() { +template void lp_solver::clpup() { int n = 0; // number of deleted rows int d; while ((d = try_to_remove_some_rows() > 0)) @@ -412,7 +412,7 @@ template void lp_solver::map_external_columns_to_ } unsigned j = col.first; auto column_info_it = m_map_from_var_index_to_column_info.find(j); - lean_assert(column_info_it != m_map_from_var_index_to_column_info.end()); + lp_assert(column_info_it != m_map_from_var_index_to_column_info.end()); auto j_column = column_info_it->second->get_column_index(); if (!is_valid(j_column)) { // j is a newcomer @@ -435,14 +435,14 @@ template void lp_solver::fill_A_from_A_values() { m_A = new static_matrix(static_cast(m_A_values.size()), number_of_core_structurals()); for (auto & t : m_A_values) { auto row_it = m_external_rows_to_core_solver_rows.find(t.first); - lean_assert(row_it != m_external_rows_to_core_solver_rows.end()); + lp_assert(row_it != m_external_rows_to_core_solver_rows.end()); unsigned row = row_it->second; for (auto k : t.second) { auto column_info_it = m_map_from_var_index_to_column_info.find(k.first); - lean_assert(column_info_it != m_map_from_var_index_to_column_info.end()); + lp_assert(column_info_it != m_map_from_var_index_to_column_info.end()); column_info *ci = column_info_it->second; unsigned col = ci->get_column_index(); - lean_assert(is_valid(col)); + lp_assert(is_valid(col)); bool col_is_flipped = m_map_from_var_index_to_column_info[k.first]->is_flipped(); if (!col_is_flipped) { (*m_A)(row, col) = k.second; @@ -456,7 +456,7 @@ template void lp_solver::fill_A_from_A_values() { template void lp_solver::fill_matrix_A_and_init_right_side() { map_external_rows_to_core_solver_rows(); map_external_columns_to_core_solver_columns(); - lean_assert(m_A == nullptr); + lp_assert(m_A == nullptr); fill_A_from_A_values(); m_b.resize(m_A->row_count()); } @@ -468,7 +468,7 @@ template void lp_solver::count_slacks_and_artific } template void lp_solver::count_slacks_and_artificials_for_row(unsigned i) { - lean_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()); auto & constraint = this->m_constraints[this->m_core_solver_rows_to_external_rows[i]]; switch (constraint.m_relation) { case Equal: @@ -504,7 +504,7 @@ template T lp_solver::low_bound_shift_for_row( template void lp_solver::fill_m_b() { for (int i = this->row_count() - 1; i >= 0; i--) { - lean_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]; auto & constraint = this->m_constraints[external_i]; this->m_b[i] = constraint.m_rs - low_bound_shift_for_row(external_i); @@ -542,13 +542,13 @@ template T lp_solver::get_column_value_with_core_ template void lp_solver::set_scaled_cost(unsigned j) { // grab original costs but modify it with the column scales - lean_assert(j < this->m_column_scale.size()); + lp_assert(j < this->m_column_scale.size()); column_info * ci = this->m_map_from_var_index_to_column_info[this->m_core_solver_columns_to_external_columns[j]]; T cost = ci->get_cost(); if (ci->is_flipped()){ cost *= -1; } - lean_assert(ci->is_fixed() == false); + lp_assert(ci->is_fixed() == false); this->m_costs[j] = cost * this->m_column_scale[j]; } } diff --git a/src/util/lp/lp_solver_instances.cpp b/src/util/lp/lp_solver_instances.cpp index 5df490cae..6e62ba7d3 100644 --- a/src/util/lp/lp_solver_instances.cpp +++ b/src/util/lp/lp_solver_instances.cpp @@ -4,37 +4,37 @@ */ #include #include "util/lp/lp_solver.hpp" -template void lean::lp_solver::add_constraint(lean::lp_relation, double, unsigned int); -template void lean::lp_solver::cleanup(); -template void lean::lp_solver::count_slacks_and_artificials(); -template void lean::lp_solver::fill_m_b(); -template void lean::lp_solver::fill_matrix_A_and_init_right_side(); -template void lean::lp_solver::flip_costs(); -template double lean::lp_solver::get_column_cost_value(unsigned int, lean::column_info*) const; -template int lean::lp_solver::get_column_index_by_name(std::string) const; -template double lean::lp_solver::get_column_value_with_core_solver(unsigned int, lean::lp_core_solver_base*) const; -template lean::column_info* lean::lp_solver::get_or_create_column_info(unsigned int); -template void lean::lp_solver::give_symbolic_name_to_column(std::string, unsigned int); -template void lean::lp_solver::print_statistics_on_A(std::ostream & out); -template bool lean::lp_solver::problem_is_empty(); -template void lean::lp_solver::scale(); -template void lean::lp_solver::set_scaled_cost(unsigned int); -template lean::lp_solver::~lp_solver(); -template void lean::lp_solver::add_constraint(lean::lp_relation, lean::mpq, unsigned int); -template void lean::lp_solver::cleanup(); -template void lean::lp_solver::count_slacks_and_artificials(); -template void lean::lp_solver::fill_m_b(); -template void lean::lp_solver::fill_matrix_A_and_init_right_side(); -template void lean::lp_solver::flip_costs(); -template lean::mpq lean::lp_solver::get_column_cost_value(unsigned int, lean::column_info*) const; -template int lean::lp_solver::get_column_index_by_name(std::string) const; -template lean::mpq lean::lp_solver::get_column_value_by_name(std::string) const; -template lean::mpq lean::lp_solver::get_column_value_with_core_solver(unsigned int, lean::lp_core_solver_base*) const; -template lean::column_info* lean::lp_solver::get_or_create_column_info(unsigned int); -template void lean::lp_solver::give_symbolic_name_to_column(std::string, unsigned int); -template void lean::lp_solver::print_statistics_on_A(std::ostream & out); -template bool lean::lp_solver::problem_is_empty(); -template void lean::lp_solver::scale(); -template void lean::lp_solver::set_scaled_cost(unsigned int); -template lean::lp_solver::~lp_solver(); -template double lean::lp_solver::get_column_value_by_name(std::string) const; +template void lp::lp_solver::add_constraint(lp::lp_relation, double, unsigned int); +template void lp::lp_solver::clpup(); +template void lp::lp_solver::count_slacks_and_artificials(); +template void lp::lp_solver::fill_m_b(); +template void lp::lp_solver::fill_matrix_A_and_init_right_side(); +template void lp::lp_solver::flip_costs(); +template double lp::lp_solver::get_column_cost_value(unsigned int, lp::column_info*) const; +template int lp::lp_solver::get_column_index_by_name(std::string) const; +template double lp::lp_solver::get_column_value_with_core_solver(unsigned int, lp::lp_core_solver_base*) const; +template lp::column_info* lp::lp_solver::get_or_create_column_info(unsigned int); +template void lp::lp_solver::give_symbolic_name_to_column(std::string, unsigned int); +template void lp::lp_solver::print_statistics_on_A(std::ostream & out); +template bool lp::lp_solver::problem_is_empty(); +template void lp::lp_solver::scale(); +template void lp::lp_solver::set_scaled_cost(unsigned int); +template lp::lp_solver::~lp_solver(); +template void lp::lp_solver::add_constraint(lp::lp_relation, lp::mpq, unsigned int); +template void lp::lp_solver::clpup(); +template void lp::lp_solver::count_slacks_and_artificials(); +template void lp::lp_solver::fill_m_b(); +template void lp::lp_solver::fill_matrix_A_and_init_right_side(); +template void lp::lp_solver::flip_costs(); +template lp::mpq lp::lp_solver::get_column_cost_value(unsigned int, lp::column_info*) const; +template int lp::lp_solver::get_column_index_by_name(std::string) const; +template lp::mpq lp::lp_solver::get_column_value_by_name(std::string) const; +template lp::mpq lp::lp_solver::get_column_value_with_core_solver(unsigned int, lp::lp_core_solver_base*) const; +template lp::column_info* lp::lp_solver::get_or_create_column_info(unsigned int); +template void lp::lp_solver::give_symbolic_name_to_column(std::string, unsigned int); +template void lp::lp_solver::print_statistics_on_A(std::ostream & out); +template bool lp::lp_solver::problem_is_empty(); +template void lp::lp_solver::scale(); +template void lp::lp_solver::set_scaled_cost(unsigned int); +template lp::lp_solver::~lp_solver(); +template double lp::lp_solver::get_column_value_by_name(std::string) const; diff --git a/src/util/lp/lp_utils.cpp b/src/util/lp/lp_utils.cpp index 8cb98974e..7d5f46f2d 100644 --- a/src/util/lp/lp_utils.cpp +++ b/src/util/lp/lp_utils.cpp @@ -4,7 +4,7 @@ */ #include "util/lp/lp_utils.h" #ifdef lp_for_z3 -namespace lean { +namespace lp { double numeric_traits::g_zero = 0.0; double numeric_traits::g_one = 1.0; } diff --git a/src/util/lp/lp_utils.h b/src/util/lp/lp_utils.h index 2be15d79a..e1d5c5b8a 100644 --- a/src/util/lp/lp_utils.h +++ b/src/util/lp/lp_utils.h @@ -27,14 +27,14 @@ bool contains(const std::unordered_map & map, const A& key) { #define LEAN_DEBUG 1 #endif -namespace lean { +namespace lp { inline void throw_exception(const std::string & str) { throw default_exception(str); } typedef z3_exception exception; -#define lean_assert(_x_) { SASSERT(_x_); } - inline void lean_unreachable() { lean_assert(false); } +#define lp_assert(_x_) { SASSERT(_x_); } + inline void lp_unreachable() { lp_assert(false); } template inline X zero_of_type() { return numeric_traits::zero(); } template inline X one_of_type() { return numeric_traits::one(); } template inline bool is_zero(const X & v) { return numeric_traits::is_zero(v); } @@ -68,8 +68,8 @@ template struct hash> { }; template<> -struct hash> { - inline size_t operator()(const lean::numeric_pair & v) const { +struct hash> { + inline size_t operator()(const lp::numeric_pair & v) const { size_t seed = 0; hash_combine(seed, v.x); hash_combine(seed, v.y); @@ -91,26 +91,26 @@ struct hash> { #endif namespace std { template<> -struct hash { - inline size_t operator()(const lean::mpq & v) const { +struct hash { + inline size_t operator()(const lp::mpq & v) const { return v.hash(); } }; } -namespace lean { +namespace lp { template inline bool precise() { return numeric_traits::precise();} template inline X one_of_type() { return numeric_traits::one(); } template inline bool is_zero(const X & v) { return numeric_traits::is_zero(v); } template inline double get_double(const X & v) { return numeric_traits::get_double(v); } template inline T zero_of_type() {return numeric_traits::zero();} inline void throw_exception(std::string str) { throw exception(str); } -template inline T from_string(std::string const & ) { lean_unreachable();} +template inline T from_string(std::string const & ) { lp_unreachable();} template <> double inline from_string(std::string const & str) { return atof(str.c_str());} template <> mpq inline from_string(std::string const & str) { return mpq(atof(str.c_str())); } -} // closing lean +} // closing lp template inline void hash_combine(std::size_t & seed, const T & v) { seed ^= std::hash()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); @@ -126,8 +126,8 @@ template struct hash> { } }; template<> -struct hash> { - inline size_t operator()(const lean::numeric_pair & v) const { +struct hash> { + inline size_t operator()(const lp::numeric_pair & v) const { size_t seed = 0; hash_combine(seed, v.x); hash_combine(seed, v.y); diff --git a/src/util/lp/lu.h b/src/util/lp/lu.h index 0d8163a14..ff95fe258 100644 --- a/src/util/lp/lu.h +++ b/src/util/lp/lu.h @@ -18,7 +18,7 @@ #include "util/lp/row_eta_matrix.h" #include "util/lp/square_dense_submatrix.h" #include "util/lp/dense_matrix.h" -namespace lean { +namespace lp { #ifdef LEAN_DEBUG template // print the nr x nc submatrix at the top left corner void print_submatrix(sparse_matrix & m, unsigned mr, unsigned nc); @@ -32,7 +32,7 @@ void print_matrix(sparse_matrix& m, std::ostream & out); template X dot_product(const vector & a, const vector & b) { - lean_assert(a.size() == b.size()); + lp_assert(a.size() == b.size()); auto r = zero_of_type(); for (unsigned i = 0; i < a.size(); i++) { r += a[i] * b[i]; @@ -99,7 +99,7 @@ public: m_i = p.apply_reverse(m_i); #ifdef LEAN_DEBUG - // lean_assert(*this == deb); + // lp_assert(*this == deb); #endif } }; // end of one_elem_on_diag @@ -291,7 +291,7 @@ public: bool need_to_refactor() { return m_refactor_counter >= 200; } void adjust_dimension_with_matrix_A() { - lean_assert(m_A.row_count() >= m_dim); + lp_assert(m_A.row_count() >= m_dim); m_dim = m_A.row_count(); m_U.resize(m_dim); m_Q.resize(m_dim); @@ -305,7 +305,7 @@ public: unsigned m = m_A.row_count(); unsigned m_prev = m_U.dimension(); - lean_assert(m_A.column_count() == heading.size()); + lp_assert(m_A.column_count() == heading.size()); for (unsigned i = m_prev; i < m; i++) { for (const row_cell & c : m_A.m_rows[i]) { @@ -321,14 +321,14 @@ public: void add_last_rows_to_B(const vector & heading, const std::unordered_set & columns_to_replace) { unsigned m = m_A.row_count(); - lean_assert(m_A.column_count() == heading.size()); + lp_assert(m_A.column_count() == heading.size()); adjust_dimension_with_matrix_A(); m_w_for_extension.resize(m); // At this moment the LU is correct // for B extended by only by ones at the diagonal in the lower right corner for (unsigned j :columns_to_replace) { - lean_assert(heading[j] >= 0); + lp_assert(heading[j] >= 0); replace_column_with_only_change_at_last_rows(j, heading[j]); if (get_status() == LU_status::Degenerated) break; diff --git a/src/util/lp/lu.hpp b/src/util/lp/lu.hpp index 2d2c7c7c4..c602892ac 100644 --- a/src/util/lp/lu.hpp +++ b/src/util/lp/lu.hpp @@ -9,7 +9,7 @@ #include #include "util/debug.h" #include "util/lp/lu.h" -namespace lean { +namespace lp { #ifdef LEAN_DEBUG template // print the nr x nc submatrix at the top left corner void print_submatrix(sparse_matrix & m, unsigned mr, unsigned nc, std::ostream & out) { @@ -122,29 +122,29 @@ lu::lu(static_matrix const & A, m_failure(false), m_row_eta_work_vector(A.row_count()), m_refactor_counter(0) { - lean_assert(!(numeric_traits::precise() && settings.use_tableau())); + lp_assert(!(numeric_traits::precise() && settings.use_tableau())); #ifdef LEAN_DEBUG debug_test_of_basis(A, basis); #endif ++m_settings.st().m_num_factorizations; create_initial_factorization(); #ifdef LEAN_DEBUG - // lean_assert(check_correctness()); + // lp_assert(check_correctness()); #endif } template void lu::debug_test_of_basis(static_matrix const & A, vector & basis) { std::set set; for (unsigned i = 0; i < A.row_count(); i++) { - lean_assert(basis[i]< A.column_count()); + lp_assert(basis[i]< A.column_count()); set.insert(basis[i]); } - lean_assert(set.size() == A.row_count()); + lp_assert(set.size() == A.row_count()); } template void lu::solve_By(indexed_vector & y) { - lean_assert(false); // not implemented + lp_assert(false); // not implemented // init_vector_y(y); // solve_By_when_y_is_ready(y); } @@ -277,20 +277,20 @@ void lu::solve_yB(vector& y) { template void lu::solve_yB_indexed(indexed_vector& y) { - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); // first solve yU = cb*R(-1) m_R.apply_reverse_from_right_to_T(y); // got y = cb*R(-1) - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); m_U.solve_y_U_indexed(y, m_settings); // got y*U=cb*R(-1) - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); m_Q.apply_reverse_from_right_to_T(y); - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); for (auto e = m_tail.rbegin(); e != m_tail.rend(); ++e) { #ifdef LEAN_DEBUG (*e)->set_number_of_columns(m_dim); #endif (*e)->apply_from_right(y); - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); } } @@ -304,8 +304,8 @@ void lu::add_delta_to_solution(const vector& yc, vector& y){ template void lu::add_delta_to_solution_indexed(indexed_vector& y) { // the delta sits in m_y_copy, put result into y - lean_assert(y.is_OK()); - lean_assert(m_y_copy.is_OK()); + lp_assert(y.is_OK()); + lp_assert(m_y_copy.is_OK()); m_ii.clear(); m_ii.resize(y.data_size()); for (unsigned i : y.m_index) @@ -315,7 +315,7 @@ void lu::add_delta_to_solution_indexed(indexed_vector& y) { if (m_ii[i] == 0) m_ii.set_value(1, i); } - lean_assert(m_ii.is_OK()); + lp_assert(m_ii.is_OK()); y.m_index.clear(); for (unsigned i : m_ii.m_index) { @@ -326,7 +326,7 @@ void lu::add_delta_to_solution_indexed(indexed_vector& y) { v = zero_of_type(); } - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); } template @@ -343,7 +343,7 @@ void lu::find_error_of_yB_indexed(const indexed_vector& y, const vector // it is a non efficient version indexed_vector yc = m_y_copy; yc.m_index.clear(); - lean_assert(!numeric_traits::precise()); + lp_assert(!numeric_traits::precise()); { vector d_basis(y.m_data.size()); @@ -364,10 +364,10 @@ void lu::find_error_of_yB_indexed(const indexed_vector& y, const vector } } #endif - lean_assert(m_ii.is_OK()); + lp_assert(m_ii.is_OK()); m_ii.clear(); m_ii.resize(y.data_size()); - lean_assert(m_y_copy.is_OK()); + lp_assert(m_y_copy.is_OK()); // put the error into m_y_copy for (auto k : y.m_index) { auto & row = m_A.m_rows[k]; @@ -399,7 +399,7 @@ void lu::find_error_of_yB_indexed(const indexed_vector& y, const vector m_y_copy.set_value(v, k); } } - lean_assert(m_y_copy.is_OK()); + lp_assert(m_y_copy.is_OK()); } @@ -415,31 +415,31 @@ void lu::solve_yB_with_error_check_indexed(indexed_vector & y, const ve solve_yB_indexed(y); } else { solve_yB(y.m_data); - y.restore_index_and_clean_from_data(); + y.restore_index_and_clp_from_data(); } return; } - lean_assert(m_y_copy.is_OK()); - lean_assert(y.is_OK()); + lp_assert(m_y_copy.is_OK()); + lp_assert(y.is_OK()); if (y.m_index.size() * ratio_of_index_size_to_all_size() < m_A.column_count()) { m_y_copy = y; solve_yB_indexed(y); - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); if (y.m_index.size() * ratio_of_index_size_to_all_size() >= m_A.column_count()) { find_error_of_yB(m_y_copy.m_data, y.m_data, basis); solve_yB(m_y_copy.m_data); add_delta_to_solution(m_y_copy.m_data, y.m_data); - y.restore_index_and_clean_from_data(); + y.restore_index_and_clp_from_data(); m_y_copy.clear_all(); } else { find_error_of_yB_indexed(y, heading, settings); // this works with m_y_copy solve_yB_indexed(m_y_copy); add_delta_to_solution_indexed(y); } - lean_assert(m_y_copy.is_OK()); + lp_assert(m_y_copy.is_OK()); } else { solve_yB_with_error_check(y.m_data, basis); - y.restore_index_and_clean_from_data(); + y.restore_index_and_clp_from_data(); } } @@ -489,7 +489,7 @@ template void lu::perform_transformations_on_w(indexed_vector& w) { apply_lp_list_to_w(w); m_Q.apply_reverse_from_left(w); - // TBD does not compile: lean_assert(numeric_traits::precise() || check_vector_for_small_values(w, m_settings)); + // TBD does not compile: lp_assert(numeric_traits::precise() || check_vector_for_small_values(w, m_settings)); } // see Chvatal 24.3 @@ -503,7 +503,7 @@ template void lu::apply_lp_list_to_w(indexed_vector & w) { for (unsigned i = 0; i < m_tail.size(); i++) { m_tail[i]->apply_from_left_to_T(w, m_settings); - // TBD does not compile: lean_assert(check_vector_for_small_values(w, m_settings)); + // TBD does not compile: lp_assert(check_vector_for_small_values(w, m_settings)); } } template @@ -595,7 +595,7 @@ void lu::check_apply_lp_lists_to_w(T * w) { permutation_matrix qr = m_Q.get_reverse(); apply_to_vector(qr, w); for (int i = m_dim - 1; i >= 0; i--) { - lean_assert(abs(w[i] - w[i]) < 0.0000001); + lp_assert(abs(w[i] - w[i]) < 0.0000001); } } @@ -640,7 +640,7 @@ bool lu::is_correct(const vector& basis) { #ifdef LEAN_DEBUG template dense_matrix lu::tail_product() { - lean_assert(tail_size() > 0); + lp_assert(tail_size() > 0); dense_matrix left_side = permutation_matrix(m_dim); for (unsigned i = 0; i < tail_size(); i++) { matrix* lp = get_lp_matrix(i); @@ -690,8 +690,8 @@ template bool lu::all_columns_and_rows_are_active() { unsigned i = m_dim; while (i--) { - lean_assert(m_U.col_is_active(i)); - lean_assert(m_U.row_is_active(i)); + lp_assert(m_U.col_is_active(i)); + lp_assert(m_U.row_is_active(i)); } return true; } @@ -733,9 +733,9 @@ void lu::create_initial_factorization(){ } } if (j == m_dim) { - // TBD does not compile: lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); - // lean_assert(is_correct()); - // lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); + // TBD does not compile: lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); + // lp_assert(is_correct()); + // lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); return; } j++; @@ -748,12 +748,12 @@ void lu::create_initial_factorization(){ } } m_dense_LU->update_parent_matrix(m_settings); - lean_assert(m_dense_LU->is_L_matrix()); + lp_assert(m_dense_LU->is_L_matrix()); m_dense_LU->conjugate_by_permutation(m_Q); push_matrix_to_tail(m_dense_LU); m_refactor_counter = 0; - // lean_assert(is_correct()); - // lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); + // lp_assert(is_correct()); + // lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); } template @@ -780,7 +780,7 @@ void lu::scan_last_row_to_work_vector(unsigned lowest_row_of_the_bump) { vector> & last_row_vec = m_U.get_row_values(m_U.adjust_row(lowest_row_of_the_bump)); for (auto & iv : last_row_vec) { if (is_zero(iv.m_value)) continue; - lean_assert(!m_settings.abs_val_is_smaller_than_drop_tolerance(iv.m_value)); + lp_assert(!m_settings.abs_val_is_smaller_than_drop_tolerance(iv.m_value)); unsigned adjusted_col = m_U.adjust_column_inverse(iv.m_index); if (adjusted_col < lowest_row_of_the_bump) { m_row_eta_work_vector.set_value(-iv.m_value, adjusted_col); @@ -801,14 +801,14 @@ void lu::pivot_and_solve_the_system(unsigned replaced_column, unsigned low vector> & row = m_U.get_row_values(aj); for (auto & iv : row) { unsigned col = m_U.adjust_column_inverse(iv.m_index); - lean_assert(col >= j || numeric_traits::is_zero(iv.m_value)); + lp_assert(col >= j || numeric_traits::is_zero(iv.m_value)); if (col == j) continue; if (numeric_traits::is_zero(iv.m_value)) { continue; } // the -v is for solving the system ( to zero the last row), and +v is for pivoting T delta = col < lowest_row_of_the_bump? -v * iv.m_value: v * iv.m_value; - lean_assert(numeric_traits::is_zero(delta) == false); + lp_assert(numeric_traits::is_zero(delta) == false); @@ -885,16 +885,16 @@ void lu::replace_column(T pivot_elem_for_checking, indexed_vector & w, push_matrix_to_tail(row_eta); } calculate_Lwave_Pwave_for_bump(replaced_column, lowest_row_of_the_bump); - // lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); - // lean_assert(w.is_OK() && m_row_eta_work_vector.is_OK()); + // lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); + // lp_assert(w.is_OK() && m_row_eta_work_vector.is_OK()); } template void lu::calculate_Lwave_Pwave_for_bump(unsigned replaced_column, unsigned lowest_row_of_the_bump){ T diagonal_elem; if (replaced_column < lowest_row_of_the_bump) { diagonal_elem = m_row_eta_work_vector[lowest_row_of_the_bump]; - // lean_assert(m_row_eta_work_vector.is_OK()); - m_U.set_row_from_work_vector_and_clean_work_vector_not_adjusted(m_U.adjust_row(lowest_row_of_the_bump), m_row_eta_work_vector, m_settings); + // lp_assert(m_row_eta_work_vector.is_OK()); + m_U.set_row_from_work_vector_and_clp_work_vector_not_adjusted(m_U.adjust_row(lowest_row_of_the_bump), m_row_eta_work_vector, m_settings); } else { diagonal_elem = m_U(lowest_row_of_the_bump, lowest_row_of_the_bump); // todo - get it more efficiently } @@ -904,7 +904,7 @@ void lu::calculate_Lwave_Pwave_for_bump(unsigned replaced_column, unsigned } calculate_Lwave_Pwave_for_last_row(lowest_row_of_the_bump, diagonal_elem); - // lean_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); + // lp_assert(m_U.is_upper_triangular_and_maximums_are_set_correctly_in_rows(m_settings)); } template @@ -930,8 +930,8 @@ void init_factorization(lu* & factorization, static_matrix & m_A, ve #ifdef LEAN_DEBUG template dense_matrix get_B(lu& f, const vector& basis) { - lean_assert(basis.size() == f.dimension()); - lean_assert(basis.size() == f.m_U.dimension()); + lp_assert(basis.size() == f.dimension()); + lp_assert(basis.size() == f.m_U.dimension()); dense_matrix B(f.dimension(), f.dimension()); for (unsigned i = 0; i < f.dimension(); i++) for (unsigned j = 0; j < f.dimension(); j++) diff --git a/src/util/lp/lu_instances.cpp b/src/util/lp/lu_instances.cpp index c8ff7b2f4..97fa3eed9 100644 --- a/src/util/lp/lu_instances.cpp +++ b/src/util/lp/lu_instances.cpp @@ -8,56 +8,56 @@ #include "util/vector.h" #include "util/debug.h" #include "util/lp/lu.hpp" -template double lean::dot_product(vector const&, vector const&); -template lean::lu::lu(lean::static_matrix const&, vector&, lean::lp_settings&); -template void lean::lu::push_matrix_to_tail(lean::tail_matrix*); -template void lean::lu::replace_column(double, lean::indexed_vector&, unsigned); -template void lean::lu::solve_Bd(unsigned int, lean::indexed_vector&, lean::indexed_vector&); -template lean::lu::~lu(); -template void lean::lu::push_matrix_to_tail(lean::tail_matrix*); -template void lean::lu::solve_Bd(unsigned int, lean::indexed_vector&, lean::indexed_vector&); -template lean::lu::~lu(); -template void lean::lu >::push_matrix_to_tail(lean::tail_matrix >*); -template void lean::lu >::solve_Bd(unsigned int, lean::indexed_vector&, lean::indexed_vector&); -template lean::lu >::~lu(); -template lean::mpq lean::dot_product(vector const&, vector const&); -template void lean::init_factorization(lean::lu*&, lean::static_matrix&, vector&, lean::lp_settings&); -template void lean::init_factorization(lean::lu*&, lean::static_matrix&, vector&, lean::lp_settings&); -template void lean::init_factorization >(lean::lu >*&, lean::static_matrix >&, vector&, lean::lp_settings&); +template double lp::dot_product(vector const&, vector const&); +template lp::lu::lu(lp::static_matrix const&, vector&, lp::lp_settings&); +template void lp::lu::push_matrix_to_tail(lp::tail_matrix*); +template void lp::lu::replace_column(double, lp::indexed_vector&, unsigned); +template void lp::lu::solve_Bd(unsigned int, lp::indexed_vector&, lp::indexed_vector&); +template lp::lu::~lu(); +template void lp::lu::push_matrix_to_tail(lp::tail_matrix*); +template void lp::lu::solve_Bd(unsigned int, lp::indexed_vector&, lp::indexed_vector&); +template lp::lu::~lu(); +template void lp::lu >::push_matrix_to_tail(lp::tail_matrix >*); +template void lp::lu >::solve_Bd(unsigned int, lp::indexed_vector&, lp::indexed_vector&); +template lp::lu >::~lu(); +template lp::mpq lp::dot_product(vector const&, vector const&); +template void lp::init_factorization(lp::lu*&, lp::static_matrix&, vector&, lp::lp_settings&); +template void lp::init_factorization(lp::lu*&, lp::static_matrix&, vector&, lp::lp_settings&); +template void lp::init_factorization >(lp::lu >*&, lp::static_matrix >&, vector&, lp::lp_settings&); #ifdef LEAN_DEBUG -template void lean::print_matrix(lean::sparse_matrix&, std::ostream & out); -template void lean::print_matrix(lean::static_matrix&, std::ostream&); -template void lean::print_matrix >(lean::static_matrix >&, std::ostream&); -template void lean::print_matrix(lean::static_matrix&, std::ostream & out); -template bool lean::lu::is_correct(const vector& basis); -template bool lean::lu >::is_correct( vector const &); -template lean::dense_matrix lean::get_B(lean::lu&, const vector& basis); -template lean::dense_matrix lean::get_B(lean::lu&, vector const&); +template void lp::print_matrix(lp::sparse_matrix&, std::ostream & out); +template void lp::print_matrix(lp::static_matrix&, std::ostream&); +template void lp::print_matrix >(lp::static_matrix >&, std::ostream&); +template void lp::print_matrix(lp::static_matrix&, std::ostream & out); +template bool lp::lu::is_correct(const vector& basis); +template bool lp::lu >::is_correct( vector const &); +template lp::dense_matrix lp::get_B(lp::lu&, const vector& basis); +template lp::dense_matrix lp::get_B(lp::lu&, vector const&); #endif -template bool lean::lu::pivot_the_row(int); // NOLINT -template void lean::lu::init_vector_w(unsigned int, lean::indexed_vector&); -template void lean::lu::solve_By(vector&); -template void lean::lu::solve_By_when_y_is_ready_for_X(vector&); -template void lean::lu::solve_yB_with_error_check(vector&, const vector& basis); -template void lean::lu::solve_yB_with_error_check_indexed(lean::indexed_vector&, vector const&, const vector & basis, const lp_settings&); -template void lean::lu::replace_column(lean::mpq, lean::indexed_vector&, unsigned); -template void lean::lu::solve_By(vector&); -template void lean::lu::solve_By_when_y_is_ready_for_X(vector&); -template void lean::lu::solve_yB_with_error_check(vector&, const vector& basis); -template void lean::lu::solve_yB_with_error_check_indexed(lean::indexed_vector&, vector< int > const&, const vector & basis, const lp_settings&); -template void lean::lu >::solve_yB_with_error_check_indexed(lean::indexed_vector&, vector< int > const&, const vector & basis, const lp_settings&); -template void lean::lu >::init_vector_w(unsigned int, lean::indexed_vector&); -template void lean::lu >::replace_column(lean::mpq, lean::indexed_vector&, unsigned); -template void lean::lu >::solve_Bd_faster(unsigned int, lean::indexed_vector&); -template void lean::lu >::solve_By(vector >&); -template void lean::lu >::solve_By_when_y_is_ready_for_X(vector >&); -template void lean::lu >::solve_yB_with_error_check(vector&, const vector& basis); -template void lean::lu::solve_By(lean::indexed_vector&); -template void lean::lu::solve_By(lean::indexed_vector&); -template void lean::lu::solve_yB_indexed(lean::indexed_vector&); -template void lean::lu::solve_yB_indexed(lean::indexed_vector&); -template void lean::lu >::solve_yB_indexed(lean::indexed_vector&); -template void lean::lu::solve_By_for_T_indexed_only(lean::indexed_vector&, lean::lp_settings const&); -template void lean::lu::solve_By_for_T_indexed_only(lean::indexed_vector&, lean::lp_settings const&); +template bool lp::lu::pivot_the_row(int); // NOLINT +template void lp::lu::init_vector_w(unsigned int, lp::indexed_vector&); +template void lp::lu::solve_By(vector&); +template void lp::lu::solve_By_when_y_is_ready_for_X(vector&); +template void lp::lu::solve_yB_with_error_check(vector&, const vector& basis); +template void lp::lu::solve_yB_with_error_check_indexed(lp::indexed_vector&, vector const&, const vector & basis, const lp_settings&); +template void lp::lu::replace_column(lp::mpq, lp::indexed_vector&, unsigned); +template void lp::lu::solve_By(vector&); +template void lp::lu::solve_By_when_y_is_ready_for_X(vector&); +template void lp::lu::solve_yB_with_error_check(vector&, const vector& basis); +template void lp::lu::solve_yB_with_error_check_indexed(lp::indexed_vector&, vector< int > const&, const vector & basis, const lp_settings&); +template void lp::lu >::solve_yB_with_error_check_indexed(lp::indexed_vector&, vector< int > const&, const vector & basis, const lp_settings&); +template void lp::lu >::init_vector_w(unsigned int, lp::indexed_vector&); +template void lp::lu >::replace_column(lp::mpq, lp::indexed_vector&, unsigned); +template void lp::lu >::solve_Bd_faster(unsigned int, lp::indexed_vector&); +template void lp::lu >::solve_By(vector >&); +template void lp::lu >::solve_By_when_y_is_ready_for_X(vector >&); +template void lp::lu >::solve_yB_with_error_check(vector&, const vector& basis); +template void lp::lu::solve_By(lp::indexed_vector&); +template void lp::lu::solve_By(lp::indexed_vector&); +template void lp::lu::solve_yB_indexed(lp::indexed_vector&); +template void lp::lu::solve_yB_indexed(lp::indexed_vector&); +template void lp::lu >::solve_yB_indexed(lp::indexed_vector&); +template void lp::lu::solve_By_for_T_indexed_only(lp::indexed_vector&, lp::lp_settings const&); +template void lp::lu::solve_By_for_T_indexed_only(lp::indexed_vector&, lp::lp_settings const&); diff --git a/src/util/lp/matrix.h b/src/util/lp/matrix.h index 63fd5c01e..fb177551e 100644 --- a/src/util/lp/matrix.h +++ b/src/util/lp/matrix.h @@ -8,7 +8,7 @@ #include "util/vector.h" #include #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { // used for debugging purposes only template class matrix { diff --git a/src/util/lp/matrix.hpp b/src/util/lp/matrix.hpp index d032cab8c..45e4c3da2 100644 --- a/src/util/lp/matrix.hpp +++ b/src/util/lp/matrix.hpp @@ -7,7 +7,7 @@ #include #include #include "util/lp/matrix.h" -namespace lean { +namespace lp { template bool matrix::is_equal(const matrix& other) { if (other.row_count() != row_count() || other.column_count() != column_count()) diff --git a/src/util/lp/matrix_instances.cpp b/src/util/lp/matrix_instances.cpp index aeee62786..ae37a2e69 100644 --- a/src/util/lp/matrix_instances.cpp +++ b/src/util/lp/matrix_instances.cpp @@ -7,10 +7,10 @@ #include "util/lp/matrix.hpp" #include "util/lp/static_matrix.h" #include -template void lean::print_matrix(lean::matrix const*, std::ostream & out); -template bool lean::matrix::is_equal(lean::matrix const&); -template void lean::print_matrix >(lean::matrix > const *, std::basic_ostream > &); -template void lean::print_matrix(lean::matrix const*, std::ostream&); -template bool lean::matrix >::is_equal(lean::matrix > const&); -template bool lean::matrix::is_equal(lean::matrix const&); +template void lp::print_matrix(lp::matrix const*, std::ostream & out); +template bool lp::matrix::is_equal(lp::matrix const&); +template void lp::print_matrix >(lp::matrix > const *, std::basic_ostream > &); +template void lp::print_matrix(lp::matrix const*, std::ostream&); +template bool lp::matrix >::is_equal(lp::matrix > const&); +template bool lp::matrix::is_equal(lp::matrix const&); #endif diff --git a/src/util/lp/mps_reader.h b/src/util/lp/mps_reader.h index eb83735ca..257cf63e2 100644 --- a/src/util/lp/mps_reader.h +++ b/src/util/lp/mps_reader.h @@ -19,7 +19,7 @@ #include "util/lp/lar_solver.h" #include "util/lp/lp_utils.h" #include "util/lp/lp_solver.h" -namespace lean { +namespace lp { inline bool my_white_space(const char & a) { return a == ' ' || a == '\t'; } @@ -160,9 +160,9 @@ class mps_reader { if (m_line[i] == ' ') break; } - lean_assert(m_line.size() >= offset); - lean_assert(m_line.size() >> i); - lean_assert(i >= offset); + lp_assert(m_line.size() >= offset); + lp_assert(m_line.size() >> i); + lp_assert(i >= offset); return m_line.substr(offset, i - offset); } @@ -497,7 +497,7 @@ class mps_reader { void create_or_update_bound() { const unsigned name_offset = 14; - lean_assert(m_line.size() >= 14); + lp_assert(m_line.size() >= 14); vector bound_string = split_and_trim(m_line.substr(name_offset, m_line.size())); if (bound_string.size() == 0) { @@ -603,7 +603,7 @@ class mps_reader { } for (auto s : row_with_range->m_row_columns) { - lean_assert(m_columns.find(s.first) != m_columns.end()); + lp_assert(m_columns.find(s.first) != m_columns.end()); other_bound_range_row->m_row_columns[s.first] = s.second; } } @@ -679,7 +679,7 @@ class mps_reader { if (row->m_name != m_cost_row_name) { solver->add_constraint(get_relation_from_row(row->m_type), row->m_right_side, row->m_index); for (auto s : row->m_row_columns) { - lean_assert(m_columns.find(s.first) != m_columns.end()); + lp_assert(m_columns.find(s.first) != m_columns.end()); solver->set_row_column_coefficient(row->m_index, m_columns[s.first]->m_index, s.second); } } else { @@ -714,7 +714,7 @@ class mps_reader { void set_solver_cost(row * row, lp_solver *solver) { for (auto s : row->m_row_columns) { std::string name = s.first; - lean_assert(m_columns.find(name) != m_columns.end()); + lp_assert(m_columns.find(name) != m_columns.end()); mps_reader::column * col = m_columns[name]; solver->set_cost_for_column(col->m_index, s.second); } @@ -723,7 +723,7 @@ class mps_reader { public: void set_message_stream(std::ostream * o) { - lean_assert(o != nullptr); + lp_assert(o != nullptr); m_message_stream = o; } vector column_names() { diff --git a/src/util/lp/nra_solver.cpp b/src/util/lp/nra_solver.cpp index 81372be32..efa003b37 100644 --- a/src/util/lp/nra_solver.cpp +++ b/src/util/lp/nra_solver.cpp @@ -14,23 +14,23 @@ namespace nra { struct mon_eq { - mon_eq(lean::var_index v, unsigned sz, lean::var_index const* vs): + mon_eq(lp::var_index v, unsigned sz, lp::var_index const* vs): m_v(v), m_vs(sz, vs) {} - lean::var_index m_v; - svector m_vs; + lp::var_index m_v; + svector m_vs; }; struct solver::imp { - lean::lar_solver& s; + lp::lar_solver& s; reslimit& m_limit; params_ref m_params; u_map m_lp2nl; // map from lar_solver variables to nlsat::solver variables scoped_ptr m_nlsat; vector m_monomials; unsigned_vector m_monomials_lim; - mutable std::unordered_map m_variable_values; // current model + mutable std::unordered_map m_variable_values; // current model - imp(lean::lar_solver& s, reslimit& lim, params_ref const& p): + imp(lp::lar_solver& s, reslimit& lim, params_ref const& p): s(s), m_limit(lim), m_params(p) { @@ -40,7 +40,7 @@ namespace nra { return !m_monomials.empty() && !check_assignments(); } - void add(lean::var_index v, unsigned sz, lean::var_index const* vs) { + void add(lp::var_index v, unsigned sz, lp::var_index const* vs) { m_monomials.push_back(mon_eq(v, sz, vs)); } @@ -87,7 +87,7 @@ namespace nra { TBD: use partial model from lra_solver to prime the state of nlsat_solver. TBD: explore more incremental ways of applying nlsat (using assumptions) */ - lbool check(lean::explanation_t& ex) { + lbool check(lp::explanation_t& ex) { SASSERT(need_check()); m_nlsat = alloc(nlsat::solver, m_limit, m_params); m_lp2nl.reset(); @@ -168,31 +168,31 @@ namespace nra { nlsat::literal lit; nlsat::assumption a = this + idx; switch (k) { - case lean::lconstraint_kind::LE: + case lp::lconstraint_kind::LE: lit = ~m_nlsat->mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even); break; - case lean::lconstraint_kind::GE: + case lp::lconstraint_kind::GE: lit = ~m_nlsat->mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even); break; - case lean::lconstraint_kind::LT: + case lp::lconstraint_kind::LT: lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::LT, 1, ps, is_even); break; - case lean::lconstraint_kind::GT: + case lp::lconstraint_kind::GT: lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::GT, 1, ps, is_even); break; - case lean::lconstraint_kind::EQ: + case lp::lconstraint_kind::EQ: lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, is_even); break; } m_nlsat->mk_clause(1, &lit, a); } - bool is_int(lean::var_index v) { + bool is_int(lp::var_index v) { return s.var_is_int(v); } - polynomial::var lp2nl(lean::var_index v) { + polynomial::var lp2nl(lp::var_index v) { polynomial::var r; if (!m_lp2nl.find(v, r)) { r = m_nlsat->mk_var(is_int(v)); @@ -201,7 +201,7 @@ namespace nra { return r; } - nlsat::anum const& value(lean::var_index v) const { + nlsat::anum const& value(lp::var_index v) const { return m_nlsat->value(m_lp2nl.find(v)); } @@ -221,7 +221,7 @@ namespace nra { } }; - solver::solver(lean::lar_solver& s, reslimit& lim, params_ref const& p) { + solver::solver(lp::lar_solver& s, reslimit& lim, params_ref const& p) { m_imp = alloc(imp, s, lim, p); } @@ -229,11 +229,11 @@ namespace nra { dealloc(m_imp); } - void solver::add_monomial(lean::var_index v, unsigned sz, lean::var_index const* vs) { + void solver::add_monomial(lp::var_index v, unsigned sz, lp::var_index const* vs) { m_imp->add(v, sz, vs); } - lbool solver::check(lean::explanation_t& ex) { + lbool solver::check(lp::explanation_t& ex) { return m_imp->check(ex); } @@ -253,7 +253,7 @@ namespace nra { return m_imp->display(out); } - nlsat::anum const& solver::value(lean::var_index v) const { + nlsat::anum const& solver::value(lp::var_index v) const { return m_imp->value(v); } diff --git a/src/util/lp/nra_solver.h b/src/util/lp/nra_solver.h index 0b02e7136..68c9e98e5 100644 --- a/src/util/lp/nra_solver.h +++ b/src/util/lp/nra_solver.h @@ -10,7 +10,7 @@ #include "util/params.h" #include "nlsat/nlsat_solver.h" -namespace lean { +namespace lp { class lar_solver; } @@ -25,7 +25,7 @@ namespace nra { public: - solver(lean::lar_solver& s, reslimit& lim, params_ref const& p = params_ref()); + solver(lp::lar_solver& s, reslimit& lim, params_ref const& p = params_ref()); ~solver(); @@ -33,13 +33,13 @@ namespace nra { \brief Add a definition v = vs[0]*vs[1]*...*vs[sz-1] The variable v is equal to the product of variables vs. */ - void add_monomial(lean::var_index v, unsigned sz, lean::var_index const* vs); + void add_monomial(lp::var_index v, unsigned sz, lp::var_index const* vs); /* \brief Check feasiblity of linear constraints augmented by polynomial definitions that are added. */ - lbool check(lean::explanation_t& ex); + lbool check(lp::explanation_t& ex); /* \brief determine whether nra check is needed. @@ -49,7 +49,7 @@ namespace nra { /* \brief Access model. */ - nlsat::anum const& value(lean::var_index v) const; + nlsat::anum const& value(lp::var_index v) const; nlsat::anum_manager& am(); diff --git a/src/util/lp/numeric_pair.h b/src/util/lp/numeric_pair.h index db7b71119..b41f6b565 100644 --- a/src/util/lp/numeric_pair.h +++ b/src/util/lp/numeric_pair.h @@ -17,11 +17,11 @@ // include "util/numerics/mpq.h" // include "util/numerics/numeric_traits.h" #endif -namespace lean { +namespace lp { #ifdef lp_for_z3 // rename rationals typedef rational mpq; #else - typedef lean::mpq mpq; + typedef lp::mpq mpq; #endif @@ -73,8 +73,8 @@ template struct convert_struct { static X convert(const Y & y){ return X(y);} static bool is_epsilon_small(const X & x, const double & y) { return std::abs(numeric_traits::get_double(x)) < y; } - static bool below_bound_numeric(const X &, const X &, const Y &) { /*lean_unreachable();*/ return false;} - static bool above_bound_numeric(const X &, const X &, const Y &) { /*lean_unreachable();*/ return false; } + static bool below_bound_numeric(const X &, const X &, const Y &) { /*lp_unreachable();*/ return false;} + static bool above_bound_numeric(const X &, const X &, const Y &) { /*lp_unreachable();*/ return false; } }; @@ -144,7 +144,7 @@ struct numeric_pair { } numeric_pair operator/(const numeric_pair &) const { - // lean_unreachable(); + // lp_unreachable(); } @@ -153,7 +153,7 @@ struct numeric_pair { } numeric_pair operator*(const numeric_pair & /*a*/) const { - // lean_unreachable(); + // lp_unreachable(); } numeric_pair& operator+=(const numeric_pair & a) { @@ -188,7 +188,7 @@ struct numeric_pair { return numeric_pair(-x, -y); } - static bool precize() { return lean::numeric_traits::precize();} + static bool precize() { return lp::numeric_traits::precize();} bool is_zero() const { return x.is_zero() && y.is_zero(); } @@ -230,15 +230,15 @@ numeric_pair operator/(const numeric_pair & r, const X & a) { } // template bool precise() { return numeric_traits::precise();} -template double get_double(const lean::numeric_pair & ) { /* lean_unreachable(); */ return 0;} +template double get_double(const lp::numeric_pair & ) { /* lp_unreachable(); */ return 0;} template -class numeric_traits> { +class numeric_traits> { public: static bool precise() { return numeric_traits::precise();} - static lean::numeric_pair zero() { return lean::numeric_pair(numeric_traits::zero(), numeric_traits::zero()); } - static bool is_zero(const lean::numeric_pair & v) { return numeric_traits::is_zero(v.x) && numeric_traits::is_zero(v.y); } - static double get_double(const lean::numeric_pair & v){ return numeric_traits::get_double(v.x); } // just return the double of the first coordinate - static double one() { /*lean_unreachable();*/ return 0;} + static lp::numeric_pair zero() { return lp::numeric_pair(numeric_traits::zero(), numeric_traits::zero()); } + static bool is_zero(const lp::numeric_pair & v) { return numeric_traits::is_zero(v.x) && numeric_traits::is_zero(v.y); } + static double get_double(const lp::numeric_pair & v){ return numeric_traits::get_double(v.x); } // just return the double of the first coordinate + static double one() { /*lp_unreachable();*/ return 0;} static bool is_pos(const numeric_pair &p) { return numeric_traits::is_pos(p.x) || (numeric_traits::is_zero(p.x) && numeric_traits::is_pos(p.y)); @@ -268,11 +268,11 @@ struct convert_struct, double> { return convert_struct::is_epsilon_small(p.x, eps) && convert_struct::is_epsilon_small(p.y, eps); } static bool below_bound_numeric(const numeric_pair &, const numeric_pair &, const double &) { - // lean_unreachable(); + // lp_unreachable(); return false; } static bool above_bound_numeric(const numeric_pair &, const numeric_pair &, const double &) { - // lean_unreachable(); + // lp_unreachable(); return false; } }; diff --git a/src/util/lp/permutation_matrix.h b/src/util/lp/permutation_matrix.h index 4bdd57f25..e0a3ac4c1 100644 --- a/src/util/lp/permutation_matrix.h +++ b/src/util/lp/permutation_matrix.h @@ -12,7 +12,7 @@ #include "util/lp/lp_settings.h" #include "util/lp/matrix.h" #include "util/lp/tail_matrix.h" -namespace lean { +namespace lp { #ifdef LEAN_DEBUG inline bool is_even(int k) { return (k/2)*2 == k; } #endif @@ -86,7 +86,7 @@ class permutation_matrix : public tail_matrix { void apply_reverse_from_right_to_X(vector & w); void set_val(unsigned i, unsigned pi) { - lean_assert(i < size() && pi < size()); m_permutation[i] = pi; m_rev[pi] = i; } + lp_assert(i < size() && pi < size()); m_permutation[i] = pi; m_rev[pi] = i; } void transpose_from_left(unsigned i, unsigned j); diff --git a/src/util/lp/permutation_matrix.hpp b/src/util/lp/permutation_matrix.hpp index ec9af5a50..a379e1ab2 100644 --- a/src/util/lp/permutation_matrix.hpp +++ b/src/util/lp/permutation_matrix.hpp @@ -4,7 +4,7 @@ */ #include "util/vector.h" #include "util/lp/permutation_matrix.h" -namespace lean { +namespace lp { template permutation_matrix::permutation_matrix(unsigned length): m_permutation(length), m_rev(length), m_T_buffer(length), m_X_buffer(length) { for (unsigned i = 0; i < length; i++) { // do not change the direction of the loop because of the vectorization bug in clang3.3 m_permutation[i] = m_rev[i] = i; @@ -50,7 +50,7 @@ void permutation_matrix::apply_from_left(vector & w, lp_settings & ) { // deb.apply_from_left(deb_w); #endif // std::cout << " apply_from_left " << std::endl; - lean_assert(m_X_buffer.size() == w.size()); + lp_assert(m_X_buffer.size() == w.size()); unsigned i = size(); while (i-- > 0) { m_X_buffer[i] = w[m_permutation[i]]; @@ -60,7 +60,7 @@ void permutation_matrix::apply_from_left(vector & w, lp_settings & ) { w[i] = m_X_buffer[i]; } #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w, row_count())); + // lp_assert(vectors_are_equal(deb_w, w, row_count())); // delete [] deb_w; #endif } @@ -86,7 +86,7 @@ template void permutation_matrix::apply_from_righ // T * deb_w = clone_vector(w, row_count()); // deb.apply_from_right(deb_w); #endif - lean_assert(m_T_buffer.size() == w.size()); + lp_assert(m_T_buffer.size() == w.size()); for (unsigned i = 0; i < size(); i++) { m_T_buffer[i] = w[m_rev[i]]; } @@ -95,7 +95,7 @@ template void permutation_matrix::apply_from_righ w[i] = m_T_buffer[i]; } #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w, row_count())); + // lp_assert(vectors_are_equal(deb_w, w, row_count())); // delete [] deb_w; #endif } @@ -117,9 +117,9 @@ template void permutation_matrix::apply_from_righ unsigned pj = m_permutation[j]; w.set_value(buffer[i], pj); } - lean_assert(w.is_OK()); + lp_assert(w.is_OK()); #ifdef LEAN_DEBUG - lean_assert(vectors_are_equal(wcopy, w.m_data)); + lp_assert(vectors_are_equal(wcopy, w.m_data)); #endif } @@ -166,7 +166,7 @@ void permutation_matrix::apply_reverse_from_left(indexed_vector & w) { w.m_index[i] = j; } #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(deb_w, w.m_data, row_count())); + // lp_assert(vectors_are_equal(deb_w, w.m_data, row_count())); // delete [] deb_w; #endif } @@ -174,7 +174,7 @@ void permutation_matrix::apply_reverse_from_left(indexed_vector & w) { template void permutation_matrix::apply_reverse_from_left_to_T(vector & w) { // the result will be w = p(-1) * w - lean_assert(m_T_buffer.size() == w.size()); + lp_assert(m_T_buffer.size() == w.size()); unsigned i = size(); while (i-- > 0) { m_T_buffer[m_permutation[i]] = w[i]; @@ -187,7 +187,7 @@ void permutation_matrix::apply_reverse_from_left_to_T(vector & w) { template void permutation_matrix::apply_reverse_from_left_to_X(vector & w) { // the result will be w = p(-1) * w - lean_assert(m_X_buffer.size() == w.size()); + lp_assert(m_X_buffer.size() == w.size()); unsigned i = size(); while (i-- > 0) { m_X_buffer[m_permutation[i]] = w[i]; @@ -201,7 +201,7 @@ void permutation_matrix::apply_reverse_from_left_to_X(vector & w) { template void permutation_matrix::apply_reverse_from_right_to_T(vector & w) { // the result will be w = w * p(-1) - lean_assert(m_T_buffer.size() == w.size()); + lp_assert(m_T_buffer.size() == w.size()); unsigned i = size(); while (i-- > 0) { m_T_buffer[i] = w[m_permutation[i]]; @@ -219,7 +219,7 @@ void permutation_matrix::apply_reverse_from_right_to_T(indexed_vector & // vector wcopy(w.m_data); // apply_reverse_from_right_to_T(wcopy); #endif - lean_assert(w.is_OK()); + lp_assert(w.is_OK()); vector tmp; vector tmp_index(w.m_index); for (auto i : w.m_index) { @@ -232,15 +232,15 @@ void permutation_matrix::apply_reverse_from_right_to_T(indexed_vector & w.set_value(tmp[k], m_rev[j]); } - // lean_assert(w.is_OK()); - // lean_assert(vectors_are_equal(w.m_data, wcopy)); + // lp_assert(w.is_OK()); + // lp_assert(vectors_are_equal(w.m_data, wcopy)); } template void permutation_matrix::apply_reverse_from_right_to_X(vector & w) { // the result will be w = w * p(-1) - lean_assert(m_X_buffer.size() == w.size()); + lp_assert(m_X_buffer.size() == w.size()); unsigned i = size(); while (i-- > 0) { m_X_buffer[i] = w[m_permutation[i]]; @@ -253,7 +253,7 @@ void permutation_matrix::apply_reverse_from_right_to_X(vector & w) { template void permutation_matrix::transpose_from_left(unsigned i, unsigned j) { // the result will be this = (i,j)*this - lean_assert(i < size() && j < size() && i != j); + lp_assert(i < size() && j < size() && i != j); auto pi = m_rev[i]; auto pj = m_rev[j]; set_val(pi, j); @@ -262,7 +262,7 @@ template void permutation_matrix::transpose_from_ template void permutation_matrix::transpose_from_right(unsigned i, unsigned j) { // the result will be this = this * (i,j) - lean_assert(i < size() && j < size() && i != j); + lp_assert(i < size() && j < size() && i != j); auto pi = m_permutation[i]; auto pj = m_permutation[j]; set_val(i, pj); @@ -271,7 +271,7 @@ template void permutation_matrix::transpose_from_ template void permutation_matrix::multiply_by_permutation_from_left(permutation_matrix & p) { m_work_array = m_permutation; - lean_assert(p.size() == size()); + lp_assert(p.size() == size()); unsigned i = size(); while (i-- > 0) { set_val(i, m_work_array[p[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation @@ -281,7 +281,7 @@ template void permutation_matrix::multiply_by_per // this is multiplication in the matrix sense template void permutation_matrix::multiply_by_permutation_from_right(permutation_matrix & p) { m_work_array = m_permutation; - lean_assert(p.size() == size()); + lp_assert(p.size() == size()); unsigned i = size(); while (i-- > 0) set_val(i, p[m_work_array[i]]); // we have m(P)*m(Q) = m(QP), where m is the matrix of the permutation @@ -289,7 +289,7 @@ template void permutation_matrix::multiply_by_per } template void permutation_matrix::multiply_by_reverse_from_right(permutation_matrix & q){ // todo : condensed permutations ? - lean_assert(q.size() == size()); + lp_assert(q.size() == size()); m_work_array = m_permutation; // the result is this = this*q(-1) unsigned i = size(); diff --git a/src/util/lp/permutation_matrix_instances.cpp b/src/util/lp/permutation_matrix_instances.cpp index 91473fabc..756ce4325 100644 --- a/src/util/lp/permutation_matrix_instances.cpp +++ b/src/util/lp/permutation_matrix_instances.cpp @@ -6,50 +6,50 @@ #include "util/vector.h" #include "util/lp/permutation_matrix.hpp" #include "util/lp/numeric_pair.h" -template void lean::permutation_matrix::apply_from_right(vector&); -template void lean::permutation_matrix::init(unsigned int); -template void lean::permutation_matrix::init(unsigned int); -template void lean::permutation_matrix>::init(unsigned int); -template bool lean::permutation_matrix::is_identity() const; -template void lean::permutation_matrix::multiply_by_permutation_from_left(lean::permutation_matrix&); -template void lean::permutation_matrix::multiply_by_permutation_reverse_from_left(lean::permutation_matrix&); -template void lean::permutation_matrix::multiply_by_reverse_from_right(lean::permutation_matrix&); -template lean::permutation_matrix::permutation_matrix(unsigned int, vector const&); -template void lean::permutation_matrix::transpose_from_left(unsigned int, unsigned int); +template void lp::permutation_matrix::apply_from_right(vector&); +template void lp::permutation_matrix::init(unsigned int); +template void lp::permutation_matrix::init(unsigned int); +template void lp::permutation_matrix>::init(unsigned int); +template bool lp::permutation_matrix::is_identity() const; +template void lp::permutation_matrix::multiply_by_permutation_from_left(lp::permutation_matrix&); +template void lp::permutation_matrix::multiply_by_permutation_reverse_from_left(lp::permutation_matrix&); +template void lp::permutation_matrix::multiply_by_reverse_from_right(lp::permutation_matrix&); +template lp::permutation_matrix::permutation_matrix(unsigned int, vector const&); +template void lp::permutation_matrix::transpose_from_left(unsigned int, unsigned int); -template void lean::permutation_matrix::apply_from_right(vector&); -template bool lean::permutation_matrix::is_identity() const; -template void lean::permutation_matrix::multiply_by_permutation_from_left(lean::permutation_matrix&); -template void lean::permutation_matrix::multiply_by_permutation_from_right(lean::permutation_matrix&); -template void lean::permutation_matrix::multiply_by_permutation_reverse_from_left(lean::permutation_matrix&); -template void lean::permutation_matrix::multiply_by_reverse_from_right(lean::permutation_matrix&); -template lean::permutation_matrix::permutation_matrix(unsigned int); -template void lean::permutation_matrix::transpose_from_left(unsigned int, unsigned int); -template void lean::permutation_matrix::transpose_from_right(unsigned int, unsigned int); -template void lean::permutation_matrix >::apply_from_right(vector&); -template bool lean::permutation_matrix >::is_identity() const; -template void lean::permutation_matrix >::multiply_by_permutation_from_left(lean::permutation_matrix >&); -template void lean::permutation_matrix >::multiply_by_permutation_from_right(lean::permutation_matrix >&); -template void lean::permutation_matrix >::multiply_by_permutation_reverse_from_left(lean::permutation_matrix >&); -template void lean::permutation_matrix >::multiply_by_reverse_from_right(lean::permutation_matrix >&); -template lean::permutation_matrix >::permutation_matrix(unsigned int); -template void lean::permutation_matrix >::transpose_from_left(unsigned int, unsigned int); -template void lean::permutation_matrix >::transpose_from_right(unsigned int, unsigned int); -template void lean::permutation_matrix::apply_reverse_from_left(lean::indexed_vector&); -template void lean::permutation_matrix::apply_reverse_from_left_to_T(vector&); -template void lean::permutation_matrix::apply_reverse_from_right_to_T(vector&); -template void lean::permutation_matrix::transpose_from_right(unsigned int, unsigned int); -template void lean::permutation_matrix::apply_reverse_from_left(lean::indexed_vector&); -template void lean::permutation_matrix::apply_reverse_from_left_to_T(vector&); -template void lean::permutation_matrix::apply_reverse_from_right_to_T(vector&); -template void lean::permutation_matrix >::apply_reverse_from_left(lean::indexed_vector&); -template void lean::permutation_matrix >::apply_reverse_from_left_to_T(vector&); -template void lean::permutation_matrix >::apply_reverse_from_right_to_T(vector&); -template void lean::permutation_matrix::multiply_by_permutation_from_right(lean::permutation_matrix&); -template lean::permutation_matrix::permutation_matrix(unsigned int); -template void lean::permutation_matrix::apply_reverse_from_left_to_X(vector &); -template void lean::permutation_matrix< lean::mpq, lean::mpq>::apply_reverse_from_left_to_X(vector &); -template void lean::permutation_matrix< lean::mpq, lean::numeric_pair< lean::mpq> >::apply_reverse_from_left_to_X(vector> &); -template void lean::permutation_matrix::apply_reverse_from_right_to_T(lean::indexed_vector&); -template void lean::permutation_matrix::apply_reverse_from_right_to_T(lean::indexed_vector&); -template void lean::permutation_matrix >::apply_reverse_from_right_to_T(lean::indexed_vector&); +template void lp::permutation_matrix::apply_from_right(vector&); +template bool lp::permutation_matrix::is_identity() const; +template void lp::permutation_matrix::multiply_by_permutation_from_left(lp::permutation_matrix&); +template void lp::permutation_matrix::multiply_by_permutation_from_right(lp::permutation_matrix&); +template void lp::permutation_matrix::multiply_by_permutation_reverse_from_left(lp::permutation_matrix&); +template void lp::permutation_matrix::multiply_by_reverse_from_right(lp::permutation_matrix&); +template lp::permutation_matrix::permutation_matrix(unsigned int); +template void lp::permutation_matrix::transpose_from_left(unsigned int, unsigned int); +template void lp::permutation_matrix::transpose_from_right(unsigned int, unsigned int); +template void lp::permutation_matrix >::apply_from_right(vector&); +template bool lp::permutation_matrix >::is_identity() const; +template void lp::permutation_matrix >::multiply_by_permutation_from_left(lp::permutation_matrix >&); +template void lp::permutation_matrix >::multiply_by_permutation_from_right(lp::permutation_matrix >&); +template void lp::permutation_matrix >::multiply_by_permutation_reverse_from_left(lp::permutation_matrix >&); +template void lp::permutation_matrix >::multiply_by_reverse_from_right(lp::permutation_matrix >&); +template lp::permutation_matrix >::permutation_matrix(unsigned int); +template void lp::permutation_matrix >::transpose_from_left(unsigned int, unsigned int); +template void lp::permutation_matrix >::transpose_from_right(unsigned int, unsigned int); +template void lp::permutation_matrix::apply_reverse_from_left(lp::indexed_vector&); +template void lp::permutation_matrix::apply_reverse_from_left_to_T(vector&); +template void lp::permutation_matrix::apply_reverse_from_right_to_T(vector&); +template void lp::permutation_matrix::transpose_from_right(unsigned int, unsigned int); +template void lp::permutation_matrix::apply_reverse_from_left(lp::indexed_vector&); +template void lp::permutation_matrix::apply_reverse_from_left_to_T(vector&); +template void lp::permutation_matrix::apply_reverse_from_right_to_T(vector&); +template void lp::permutation_matrix >::apply_reverse_from_left(lp::indexed_vector&); +template void lp::permutation_matrix >::apply_reverse_from_left_to_T(vector&); +template void lp::permutation_matrix >::apply_reverse_from_right_to_T(vector&); +template void lp::permutation_matrix::multiply_by_permutation_from_right(lp::permutation_matrix&); +template lp::permutation_matrix::permutation_matrix(unsigned int); +template void lp::permutation_matrix::apply_reverse_from_left_to_X(vector &); +template void lp::permutation_matrix< lp::mpq, lp::mpq>::apply_reverse_from_left_to_X(vector &); +template void lp::permutation_matrix< lp::mpq, lp::numeric_pair< lp::mpq> >::apply_reverse_from_left_to_X(vector> &); +template void lp::permutation_matrix::apply_reverse_from_right_to_T(lp::indexed_vector&); +template void lp::permutation_matrix::apply_reverse_from_right_to_T(lp::indexed_vector&); +template void lp::permutation_matrix >::apply_reverse_from_right_to_T(lp::indexed_vector&); diff --git a/src/util/lp/quick_xplain.cpp b/src/util/lp/quick_xplain.cpp index df409240e..93e40ea71 100644 --- a/src/util/lp/quick_xplain.cpp +++ b/src/util/lp/quick_xplain.cpp @@ -3,7 +3,7 @@ Author: Lev Nachmanson */ #include "util/lp/lar_solver.h" -namespace lean { +namespace lp { quick_xplain::quick_xplain(vector> & explanation, const lar_solver & ls, lar_solver & qsol) : m_explanation(explanation), m_parent_solver(ls), @@ -56,7 +56,7 @@ void quick_xplain::minimize(const vector& u) { } } if (m > 0) { - lean_assert(m_qsol.constraint_stack_size() >= initial_stack_size); + lp_assert(m_qsol.constraint_stack_size() >= initial_stack_size); m_qsol.pop(m_qsol.constraint_stack_size() - initial_stack_size); for (auto j : m_x) add_constraint_to_qsol(j); @@ -73,7 +73,7 @@ void quick_xplain::minimize(const vector& u) { void quick_xplain::run(vector> & explanation, const lar_solver & ls){ if (explanation.size() <= 2) return; lar_solver qsol; - lean_assert(ls.explanation_is_correct(explanation)); + lp_assert(ls.explanation_is_correct(explanation)); quick_xplain q(explanation, ls, qsol); q.solve(); } @@ -109,7 +109,7 @@ bool quick_xplain::x_is_minimal() const { x.push_back(j); for (unsigned k = 0; k < x.size(); k++) { - lean_assert(is_feasible(x, x[k])); + lp_assert(is_feasible(x, x[k])); } return true; } @@ -117,7 +117,7 @@ bool quick_xplain::x_is_minimal() const { void quick_xplain::solve() { copy_constraints_to_local_constraints(); m_qsol.push(); - lean_assert(m_qsol.constraint_count() == 0) + lp_assert(m_qsol.constraint_count() == 0) vector u; for (unsigned k = 0; k < m_constraints_in_local_vars.size(); k++) u.push_back(k); @@ -127,10 +127,10 @@ void quick_xplain::solve() { for (unsigned i : m_x) add_constraint_to_qsol(i); m_qsol.solve(); - lean_assert(m_qsol.get_status() == INFEASIBLE); + lp_assert(m_qsol.get_status() == INFEASIBLE); m_qsol.get_infeasibility_explanation(m_explanation); - lean_assert(m_qsol.explanation_is_correct(m_explanation)); - lean_assert(x_is_minimal()); + lp_assert(m_qsol.explanation_is_correct(m_explanation)); + lp_assert(x_is_minimal()); for (auto & p : m_explanation) { p.second = this->m_local_constraint_offset_to_external_ci[m_local_ci_to_constraint_offsets[p.second]]; } diff --git a/src/util/lp/quick_xplain.h b/src/util/lp/quick_xplain.h index 9faa5f41c..952199f85 100644 --- a/src/util/lp/quick_xplain.h +++ b/src/util/lp/quick_xplain.h @@ -7,7 +7,7 @@ Author: Lev Nachmanson #include "util/vector.h" #include -namespace lean { +namespace lp { class lar_solver; // forward definition class quick_xplain { diff --git a/src/util/lp/random_updater.h b/src/util/lp/random_updater.h index 8cb9740ea..68b14c971 100644 --- a/src/util/lp/random_updater.h +++ b/src/util/lp/random_updater.h @@ -12,7 +12,7 @@ Author: Lev Nachmanson #include "util/lp/linear_combination_iterator.h" // see http://research.microsoft.com/projects/z3/smt07.pdf // The class searches for a feasible solution with as many different values of variables as it can find -namespace lean { +namespace lp { template struct numeric_pair; // forward definition class lar_core_solver; // forward definition class random_updater { diff --git a/src/util/lp/random_updater.hpp b/src/util/lp/random_updater.hpp index 7c6a0539f..ced6a3767 100644 --- a/src/util/lp/random_updater.hpp +++ b/src/util/lp/random_updater.hpp @@ -6,7 +6,7 @@ #include "util/lp/static_matrix.h" #include "util/lp/lar_solver.h" #include "util/vector.h" -namespace lean { +namespace lp { @@ -36,7 +36,7 @@ random_updater::interval random_updater::get_interval_of_non_basic_var(unsigned ret.set_upper_bound(m_core_solver.m_r_upper_bounds[j]); break; default: - lean_assert(false); + lp_assert(false); } return ret; } @@ -44,15 +44,15 @@ random_updater::interval random_updater::get_interval_of_non_basic_var(unsigned void random_updater::diminish_interval_for_basic_var(numeric_pair& nb_x, unsigned j, mpq & a, interval & r) { - lean_assert(m_core_solver.m_r_heading[j] >= 0); + lp_assert(m_core_solver.m_r_heading[j] >= 0); numeric_pair delta; - lean_assert(a != zero_of_type()); + lp_assert(a != zero_of_type()); switch (m_core_solver.get_column_type(j)) { case column_type::free_column: break; case column_type::low_bound: delta = m_core_solver.m_r_x[j] - m_core_solver.m_r_low_bounds[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); if (a > 0) { r.set_upper_bound(nb_x + delta / a); } else { @@ -61,7 +61,7 @@ void random_updater::diminish_interval_for_basic_var(numeric_pair& nb_x, un break; case column_type::upper_bound: delta = m_core_solver.m_r_upper_bounds()[j] - m_core_solver.m_r_x[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); if (a > 0) { r.set_low_bound(nb_x - delta / a); } else { @@ -71,17 +71,17 @@ void random_updater::diminish_interval_for_basic_var(numeric_pair& nb_x, un case column_type::boxed: if (a > 0) { delta = m_core_solver.m_r_x[j] - m_core_solver.m_r_low_bounds[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); r.set_upper_bound(nb_x + delta / a); delta = m_core_solver.m_r_upper_bounds()[j] - m_core_solver.m_r_x[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); r.set_low_bound(nb_x - delta / a); } else { // a < 0 delta = m_core_solver.m_r_upper_bounds()[j] - m_core_solver.m_r_x[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); r.set_upper_bound(nb_x - delta / a); delta = m_core_solver.m_r_x[j] - m_core_solver.m_r_low_bounds[j]; - lean_assert(delta >= zero_of_type>()); + lp_assert(delta >= zero_of_type>()); r.set_low_bound(nb_x + delta / a); } break; @@ -90,7 +90,7 @@ void random_updater::diminish_interval_for_basic_var(numeric_pair& nb_x, un r.set_upper_bound(nb_x); break; default: - lean_assert(false); + lp_assert(false); } } @@ -113,15 +113,15 @@ random_updater::interval random_updater::find_shift_interval(unsigned j) { } void random_updater::shift_var(unsigned j, interval & r) { - lean_assert(r.contains(m_core_solver.m_r_x[j])); - lean_assert(m_core_solver.m_r_solver.column_is_feasible(j)); + lp_assert(r.contains(m_core_solver.m_r_x[j])); + lp_assert(m_core_solver.m_r_solver.column_is_feasible(j)); auto old_x = m_core_solver.m_r_x[j]; remove_value(old_x); auto new_val = m_core_solver.m_r_x[j] = get_random_from_interval(r); add_value(new_val); - lean_assert(r.contains(m_core_solver.m_r_x[j])); - lean_assert(m_core_solver.m_r_solver.column_is_feasible(j)); + lp_assert(r.contains(m_core_solver.m_r_x[j])); + lp_assert(m_core_solver.m_r_solver.column_is_feasible(j)); auto delta = m_core_solver.m_r_x[j] - old_x; unsigned i; @@ -130,9 +130,9 @@ void random_updater::shift_var(unsigned j, interval & r) { while(m_column_j->next(a, i)) { unsigned bj = m_core_solver.m_r_basis[i]; m_core_solver.m_r_x[bj] -= a * delta; - lean_assert(m_core_solver.m_r_solver.column_is_feasible(bj)); + lp_assert(m_core_solver.m_r_solver.column_is_feasible(bj)); } - lean_assert(m_core_solver.m_r_solver.A_mult_x_is_off() == false); + lp_assert(m_core_solver.m_r_solver.A_mult_x_is_off() == false); } numeric_pair random_updater::get_random_from_interval(interval & r) { @@ -143,7 +143,7 @@ numeric_pair random_updater::get_random_from_interval(interval & r) { return r.low_bound + numeric_pair(rand % range, 0); if ((!r.low_bound_is_set) && r.upper_bound_is_set) return r.upper_bound - numeric_pair(rand % range, 0); - lean_assert(r.low_bound_is_set && r.upper_bound_is_set); + lp_assert(r.low_bound_is_set && r.upper_bound_is_set); return r.low_bound + (rand % range) * (r.upper_bound - r.low_bound)/ range; } @@ -183,7 +183,7 @@ void random_updater::add_value(numeric_pair& v) { void random_updater::remove_value(numeric_pair& v) { std::unordered_map, unsigned>::iterator it = m_values.find(v); - lean_assert(it != m_values.end()); + lp_assert(it != m_values.end()); it->second--; if (it->second == 0) m_values.erase((std::unordered_map, unsigned>::const_iterator)it); diff --git a/src/util/lp/row_eta_matrix.h b/src/util/lp/row_eta_matrix.h index 90acb89f3..60adb23ae 100644 --- a/src/util/lp/row_eta_matrix.h +++ b/src/util/lp/row_eta_matrix.h @@ -10,7 +10,7 @@ #include "util/lp/sparse_vector.h" #include "util/lp/indexed_vector.h" #include "util/lp/permutation_matrix.h" -namespace lean { +namespace lp { // This is the sum of a unit matrix and a lower triangular matrix // with non-zero elements only in one row template @@ -55,7 +55,7 @@ public: } void push_back(unsigned row_index, T val ) { - lean_assert(row_index != m_row); + lp_assert(row_index != m_row); m_row_vector.push_back(row_index, val); } diff --git a/src/util/lp/row_eta_matrix.hpp b/src/util/lp/row_eta_matrix.hpp index 5758abeb8..11f8f4913 100644 --- a/src/util/lp/row_eta_matrix.hpp +++ b/src/util/lp/row_eta_matrix.hpp @@ -4,7 +4,7 @@ */ #include "util/vector.h" #include "util/lp/row_eta_matrix.h" -namespace lean { +namespace lp { template void row_eta_matrix::apply_from_left(vector & w, lp_settings &) { // #ifdef LEAN_DEBUG @@ -19,7 +19,7 @@ void row_eta_matrix::apply_from_left(vector & w, lp_settings &) { } // w[m_row] = w_at_row; // #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(clone_w, w, m_dimension)); + // lp_assert(vectors_are_equal(clone_w, w, m_dimension)); // delete [] clone_w; // #endif } @@ -43,7 +43,7 @@ void row_eta_matrix::apply_from_left_local_to_T(indexed_vector & w, lp_ auto it = std::find(w.m_index.begin(), w.m_index.end(), m_row); w.m_index.erase(it); } - // TBD: lean_assert(check_vector_for_small_values(w, settings)); + // TBD: lp_assert(check_vector_for_small_values(w, settings)); } template @@ -65,7 +65,7 @@ void row_eta_matrix::apply_from_left_local_to_X(indexed_vector & w, lp_ auto it = std::find(w.m_index.begin(), w.m_index.end(), m_row); w.m_index.erase(it); } - // TBD: does not compile lean_assert(check_vector_for_small_values(w, settings)); + // TBD: does not compile lp_assert(check_vector_for_small_values(w, settings)); } template @@ -81,14 +81,14 @@ void row_eta_matrix::apply_from_right(vector & w) { w[it.first] += w_row * it.second; } #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(clone_w, w, m_dimension)); + // lp_assert(vectors_are_equal(clone_w, w, m_dimension)); // delete clone_w; #endif } template void row_eta_matrix::apply_from_right(indexed_vector & w) { - lean_assert(w.is_OK()); + lp_assert(w.is_OK()); const T & w_row = w[m_row]; if (numeric_traits::is_zero(w_row)) return; #ifdef LEAN_DEBUG @@ -130,7 +130,7 @@ void row_eta_matrix::apply_from_right(indexed_vector & w) { } } #ifdef LEAN_DEBUG - // lean_assert(vectors_are_equal(wcopy, w.m_data)); + // lp_assert(vectors_are_equal(wcopy, w.m_data)); #endif } @@ -151,7 +151,7 @@ void row_eta_matrix::conjugate_by_permutation(permutation_matrix & p for (unsigned i = static_cast(columns.size()); i-- > 0;) m_row_vector.m_data[i].first = p.get_rev(columns[i]); #ifdef LEAN_DEBUG - // lean_assert(deb == *this); + // lp_assert(deb == *this); #endif } #ifdef LEAN_DEBUG diff --git a/src/util/lp/row_eta_matrix_instances.cpp b/src/util/lp/row_eta_matrix_instances.cpp index c32023164..7ccedf844 100644 --- a/src/util/lp/row_eta_matrix_instances.cpp +++ b/src/util/lp/row_eta_matrix_instances.cpp @@ -6,7 +6,7 @@ #include #include "util/lp/row_eta_matrix.hpp" #include "util/lp/lu.h" -namespace lean { +namespace lp { template void row_eta_matrix::conjugate_by_permutation(permutation_matrix&); template void row_eta_matrix >::conjugate_by_permutation(permutation_matrix >&); template void row_eta_matrix::conjugate_by_permutation(permutation_matrix&); diff --git a/src/util/lp/scaler.h b/src/util/lp/scaler.h index 33c5a6cc4..61869f082 100644 --- a/src/util/lp/scaler.h +++ b/src/util/lp/scaler.h @@ -11,7 +11,7 @@ #include /* exit, EXIT_FAILURE */ #include "util/lp/lp_utils.h" #include "util/lp/static_matrix.h" -namespace lean { +namespace lp { // for scaling an LP template class scaler { @@ -31,7 +31,7 @@ public: m_scaling_maximum(scaling_maximum), m_column_scale(column_scale), m_settings(settings) { - lean_assert(m_column_scale.size() == 0); + lp_assert(m_column_scale.size() == 0); m_column_scale.resize(m_A.column_count(), numeric_traits::one()); } diff --git a/src/util/lp/scaler.hpp b/src/util/lp/scaler.hpp index 69427eea0..482441d7f 100644 --- a/src/util/lp/scaler.hpp +++ b/src/util/lp/scaler.hpp @@ -5,7 +5,7 @@ #include #include "util/lp/scaler.h" #include "util/lp/numeric_pair.h" -namespace lean { +namespace lp { // for scaling an LP template T scaler::right_side_balance() { T ret = zero_of_type(); @@ -41,7 +41,7 @@ template T scaler::A_max() const { template T scaler::get_A_ratio() const { T min = A_min(); T max = A_max(); - lean_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(min)); + lp_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(min)); T ratio = max / min; return ratio; } @@ -51,7 +51,7 @@ template T scaler::get_max_ratio_on_rows() con unsigned i = m_A.row_count(); while (i--) { T den = m_A.get_min_abs_in_row(i); - lean_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(den)); + lp_assert(!m_settings.abs_val_is_smaller_than_zero_tolerance(den)); T t = m_A.get_max_abs_in_row(i)/ den; if (t > ret) ret = t; @@ -78,7 +78,7 @@ template void scaler::scale_rows_with_geometri while (i--) { T max = m_A.get_max_abs_in_row(i); T min = m_A.get_min_abs_in_row(i); - lean_assert(max > zero_of_type() && min > zero_of_type()); + lp_assert(max > zero_of_type() && min > zero_of_type()); if (is_zero(max) || is_zero(min)) continue; T gm = T(sqrt(numeric_traits::get_double(max*min))); diff --git a/src/util/lp/scaler_instances.cpp b/src/util/lp/scaler_instances.cpp index f97e8098f..de1c2b7aa 100644 --- a/src/util/lp/scaler_instances.cpp +++ b/src/util/lp/scaler_instances.cpp @@ -3,5 +3,5 @@ Author: Lev Nachmanson */ #include "util/lp/scaler.hpp" -template bool lean::scaler::scale(); -template bool lean::scaler::scale(); +template bool lp::scaler::scale(); +template bool lp::scaler::scale(); diff --git a/src/util/lp/signature_bound_evidence.h b/src/util/lp/signature_bound_evidence.h index a22c188b4..6a0b4115f 100644 --- a/src/util/lp/signature_bound_evidence.h +++ b/src/util/lp/signature_bound_evidence.h @@ -5,7 +5,7 @@ #pragma once #include "util/lp/lp_settings.h" #include "util/lp/lar_constraints.h" -namespace lean { +namespace lp { struct bound_signature { unsigned m_i; bool m_at_low; diff --git a/src/util/lp/sparse_matrix.h b/src/util/lp/sparse_matrix.h index 7256004da..0fc84f8f5 100644 --- a/src/util/lp/sparse_matrix.h +++ b/src/util/lp/sparse_matrix.h @@ -21,7 +21,7 @@ #include "util/lp/binary_heap_upair_queue.h" #include "util/lp/numeric_pair.h" #include "util/lp/int_set.h" -namespace lean { +namespace lp { // it is a square matrix template class sparse_matrix @@ -190,13 +190,13 @@ public: // set the max val as well // returns false if the resulting row is all zeroes, and true otherwise - bool set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned i0, indexed_vector & work_vec, + bool set_row_from_work_vector_and_clp_work_vector_not_adjusted(unsigned i0, indexed_vector & work_vec, lp_settings & settings); // set the max val as well // returns false if the resulting row is all zeroes, and true otherwise - bool set_row_from_work_vector_and_clean_work_vector(unsigned i0); + bool set_row_from_work_vector_and_clp_work_vector(unsigned i0); void remove_zero_elements_and_set_data_on_existing_elements(unsigned row); @@ -206,19 +206,19 @@ public: void multiply_from_right(permutation_matrix& p) { // m_dense = m_dense * p; m_column_permutation.multiply_by_permutation_from_right(p); - // lean_assert(*this == m_dense); + // lp_assert(*this == m_dense); } void multiply_from_left(permutation_matrix& p) { // m_dense = p * m_dense; m_row_permutation.multiply_by_permutation_from_left(p); - // lean_assert(*this == m_dense); + // lp_assert(*this == m_dense); } void multiply_from_left_with_reverse(permutation_matrix& p) { // m_dense = p * m_dense; m_row_permutation.multiply_by_permutation_reverse_from_left(p); - // lean_assert(*this == m_dense); + // lp_assert(*this == m_dense); } // adding delta columns at the end of the matrix @@ -231,13 +231,13 @@ public: // dense_matrix d(*this); m_column_permutation.transpose_from_left(a, b); // d.swap_columns(a, b); - // lean_assert(*this == d); + // lp_assert(*this == d); } void swap_rows(unsigned a, unsigned b) { m_row_permutation.transpose_from_right(a, b); // m_dense.swap_rows(a, b); - // lean_assert(*this == m_dense); + // lp_assert(*this == m_dense); } void divide_row_by_constant(unsigned i, const T & t, lp_settings & settings); @@ -393,7 +393,7 @@ public: void process_index_recursively_for_y_U(unsigned j, vector & sorted_rows); void resize(unsigned new_dim) { unsigned old_dim = dimension(); - lean_assert(new_dim >= old_dim); + lp_assert(new_dim >= old_dim); for (unsigned j = old_dim; j < new_dim; j++) { m_rows.push_back(vector>()); m_columns.push_back(col_header()); diff --git a/src/util/lp/sparse_matrix.hpp b/src/util/lp/sparse_matrix.hpp index 32bb8ed4e..175633eda 100644 --- a/src/util/lp/sparse_matrix.hpp +++ b/src/util/lp/sparse_matrix.hpp @@ -7,7 +7,7 @@ #include "util/lp/sparse_matrix.h" #include #include -namespace lean { +namespace lp { template void sparse_matrix::copy_column_from_static_matrix(unsigned col, static_matrix const &A, unsigned col_index_in_the_new_matrix) { vector const & A_col_vector = A.m_columns[col]; @@ -82,12 +82,12 @@ void sparse_matrix::set_with_no_adjusting(unsigned row, unsigned col, T va template void sparse_matrix::set(unsigned row, unsigned col, T val) { // should not be used in efficient code - lean_assert(row < dimension() && col < dimension()); + lp_assert(row < dimension() && col < dimension()); // m_dense.set_elem(row, col, val); row = adjust_row(row); col = adjust_column(col); set_with_no_adjusting(row, col, val); - // lean_assert(*this == m_dense); + // lp_assert(*this == m_dense); } template @@ -261,8 +261,8 @@ vector sparse_matrix::get_full_row(unsigned i) const { // Returns false if the resulting row is all zeroes, and true otherwise template bool sparse_matrix::pivot_row_to_row(unsigned i, const T& alpha, unsigned i0, lp_settings & settings ) { - lean_assert(i < dimension() && i0 < dimension()); - lean_assert(i != i0); + lp_assert(i < dimension() && i0 < dimension()); + lp_assert(i != i0); unsigned pivot_col = adjust_column(i); i = adjust_row(i); i0 = adjust_row(i0); @@ -296,7 +296,7 @@ bool sparse_matrix::pivot_row_to_row(unsigned i, const T& alpha, unsigned } - // clean the work vector + // clp the work vector for (unsigned k = 0; k < prev_size_i0; k++) { m_work_pivot_vector[i0_row_vals[k].m_index] = -1; } @@ -319,7 +319,7 @@ bool sparse_matrix::pivot_row_to_row(unsigned i, const T& alpha, unsigned // set the max val as well // returns false if the resulting row is all zeroes, and true otherwise template -bool sparse_matrix::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned i0, indexed_vector & work_vec, +bool sparse_matrix::set_row_from_work_vector_and_clp_work_vector_not_adjusted(unsigned i0, indexed_vector & work_vec, lp_settings & settings) { remove_zero_elements_and_set_data_on_existing_elements_not_adjusted(i0, work_vec, settings); // all non-zero elements in m_work_pivot_vector are new @@ -327,7 +327,7 @@ bool sparse_matrix::set_row_from_work_vector_and_clean_work_vector_not_adj if (numeric_traits::is_zero(work_vec[j])) { continue; } - lean_assert(!settings.abs_val_is_smaller_than_drop_tolerance(work_vec[j])); + lp_assert(!settings.abs_val_is_smaller_than_drop_tolerance(work_vec[j])); add_new_element(i0, adjust_column(j), work_vec[j]); work_vec[j] = numeric_traits::zero(); } @@ -372,7 +372,7 @@ void sparse_matrix::remove_zero_elements_and_set_data_on_existing_elements T val = work_vec[rj]; if (settings.abs_val_is_smaller_than_drop_tolerance(val)) { remove_element(row_vals, row_el_iv); - lean_assert(numeric_traits::is_zero(val)); + lp_assert(numeric_traits::is_zero(val)); } else { m_columns[j].m_values[row_el_iv.m_other].set_value(row_el_iv.m_value = val); work_vec[rj] = numeric_traits::zero(); @@ -393,7 +393,7 @@ void sparse_matrix::add_columns_at_the_end(unsigned delta) { template void sparse_matrix::delete_column(int i) { - lean_assert(i < dimension()); + lp_assert(i < dimension()); for (auto cell = m_columns[i].m_head; cell != nullptr;) { auto next_cell = cell->m_down; kill_cell(cell); @@ -403,7 +403,7 @@ void sparse_matrix::delete_column(int i) { template void sparse_matrix::divide_row_by_constant(unsigned i, const T & t, lp_settings & settings) { - lean_assert(!settings.abs_val_is_smaller_than_zero_tolerance(t)); + lp_assert(!settings.abs_val_is_smaller_than_zero_tolerance(t)); i = adjust_row(i); for (auto & iv : m_rows[i]) { T &v = iv.m_value; @@ -440,7 +440,7 @@ void sparse_matrix::solve_y_U(vector & y) const { // works by rows // dense_matrix deb(*this); // T * clone_y = clone_vector(y, dimension()); // deb.apply_from_right(clone_y); - // lean_assert(vectors_are_equal(rs, clone_y, dimension())); + // lp_assert(vectors_are_equal(rs, clone_y, dimension())); // delete [] clone_y; // delete [] rs; #endif @@ -474,10 +474,10 @@ void sparse_matrix::solve_y_U_indexed(indexed_vector & y, const lp_sett y.m_data[j] = zero_of_type(); } - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); #if 0 && LEAN_DEBUG if (numeric_traits::precise() == false) - lean_assert(vectors_are_equal(ycopy, y.m_data)); + lp_assert(vectors_are_equal(ycopy, y.m_data)); #endif } @@ -537,8 +537,8 @@ void sparse_matrix::add_delta_to_solution(const vector& del, vector template template void sparse_matrix::add_delta_to_solution(const indexed_vector& del, indexed_vector & y) { -// lean_assert(del.is_OK()); - // lean_assert(y.is_OK()); +// lp_assert(del.is_OK()); + // lp_assert(y.is_OK()); for (auto i : del.m_index) { y.add_value_at_index(i, del[i]); } @@ -546,24 +546,24 @@ void sparse_matrix::add_delta_to_solution(const indexed_vector& del, in template template void sparse_matrix::double_solve_U_y(indexed_vector& y, const lp_settings & settings){ - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); indexed_vector y_orig(y); // copy y aside vector active_rows; solve_U_y_indexed_only(y, settings, active_rows); - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); find_error_in_solution_U_y_indexed(y_orig, y, active_rows); // y_orig contains the error now if (y_orig.m_index.size() * ratio_of_index_size_to_all_size() < 32 * dimension()) { active_rows.clear(); solve_U_y_indexed_only(y_orig, settings, active_rows); add_delta_to_solution(y_orig, y); - y.clean_up(); + y.clp_up(); } else { // the dense version solve_U_y(y_orig.m_data); add_delta_to_solution(y_orig.m_data, y.m_data); - y.restore_index_and_clean_from_data(); + y.restore_index_and_clp_from_data(); } - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); } template template @@ -599,12 +599,12 @@ void sparse_matrix::solve_U_y(vector & y) { // it is a column wise vers // dense_matrix deb(*this); // T * clone_y = clone_vector(y, dimension()); // deb.apply_from_left(clone_y); - // lean_assert(vectors_are_equal(rs, clone_y, dimension())); + // lp_assert(vectors_are_equal(rs, clone_y, dimension())); #endif } template void sparse_matrix::process_index_recursively_for_y_U(unsigned j, vector & sorted_active_rows) { - lean_assert(m_processed[j] == false); + lp_assert(m_processed[j] == false); m_processed[j]=true; auto & row = m_rows[adjust_row(j)]; for (auto & c : row) { @@ -619,7 +619,7 @@ void sparse_matrix::process_index_recursively_for_y_U(unsigned j, vector void sparse_matrix::process_column_recursively(unsigned j, vector & sorted_active_rows) { - lean_assert(m_processed[j] == false); + lp_assert(m_processed[j] == false); auto & mc = m_columns[adjust_column(j)].m_values; for (auto & iv : mc) { unsigned i = adjust_row_inverse(iv.m_index); @@ -684,12 +684,12 @@ void sparse_matrix::solve_U_y_indexed_only(indexed_vector & y, const lp y[j] = zero_of_type(); } - lean_assert(y.is_OK()); + lp_assert(y.is_OK()); #ifdef LEAN_DEBUG // dense_matrix deb(this); // vector clone_y(y.m_data); // deb.apply_from_left(clone_y); - // lean_assert(vectors_are_equal(rs, clone_y)); + // lp_assert(vectors_are_equal(rs, clone_y)); #endif } @@ -802,7 +802,7 @@ void sparse_matrix::add_new_elements_of_w_and_clear_w(unsigned column_to_r unsigned ai = adjust_row(i); add_new_element(ai, column_to_replace, w_at_i); auto & row_chunk = m_rows[ai]; - lean_assert(row_chunk.size() > 0); + lp_assert(row_chunk.size() > 0); if (abs(w_at_i) > abs(row_chunk[0].m_value)) put_max_index_to_0(row_chunk, static_cast(row_chunk.size()) - 1); } @@ -833,7 +833,7 @@ unsigned sparse_matrix::pivot_score(unsigned i, unsigned j) { template void sparse_matrix::enqueue_domain_into_pivot_queue() { - lean_assert(m_pivot_queue.size() == 0); + lp_assert(m_pivot_queue.size() == 0); for (unsigned i = 0; i < dimension(); i++) { auto & rh = m_rows[i]; unsigned rnz = static_cast(rh.size()); @@ -919,7 +919,7 @@ void sparse_matrix::update_active_pivots(unsigned row) { for (const auto & iv : m_rows[arow]) { col_header & ch = m_columns[iv.m_index]; int cols = static_cast(ch.m_values.size()) - ch.m_shortened_markovitz - 1; - lean_assert(cols >= 0); + lp_assert(cols >= 0); for (const auto &ivc : ch.m_values) { unsigned i = ivc.m_index; if (adjust_row_inverse(i) <= row) continue; // the i is not an active row @@ -945,7 +945,7 @@ bool sparse_matrix::shorten_active_matrix(unsigned row, eta_matrix * for (auto & iv : row_values) { const col_header& ch = m_columns[iv.m_index]; int cnz = static_cast(ch.m_values.size()) - ch.m_shortened_markovitz - 1; - lean_assert(cnz >= 0); + lp_assert(cnz >= 0); m_pivot_queue.enqueue(row, iv.m_index, rnz * cnz); } } @@ -961,7 +961,7 @@ unsigned sparse_matrix::pivot_score_without_shortened_counters(unsigned i, if (adjust_row_inverse(iv.m_index) < k) cnz--; } - lean_assert(cnz > 0); + lp_assert(cnz > 0); return m_rows[i].m_values.size() * (cnz - 1); } #ifdef LEAN_DEBUG @@ -971,15 +971,15 @@ bool sparse_matrix::can_improve_score_for_row(unsigned row, unsigned score auto & row_vals = m_rows[arow].m_values; auto & begin_iv = row_vals[0]; T row_max = abs(begin_iv.m_value); - lean_assert(adjust_column_inverse(begin_iv.m_index) >= k); + lp_assert(adjust_column_inverse(begin_iv.m_index) >= k); if (pivot_score_without_shortened_counters(arow, begin_iv.m_index, k) < score) { print_active_matrix(k); return true; } for (unsigned jj = 1; jj < row_vals.size(); jj++) { auto & iv = row_vals[jj]; - lean_assert(adjust_column_inverse(iv.m_index) >= k); - lean_assert(abs(iv.m_value) <= row_max); + lp_assert(adjust_column_inverse(iv.m_index) >= k); + lp_assert(abs(iv.m_value) <= row_max); if (c_partial_pivoting * abs(iv.m_value) < row_max) continue; if (pivot_score_without_shortened_counters(arow, iv.m_index, k) < score) { print_active_matrix(k); @@ -993,7 +993,7 @@ template bool sparse_matrix::really_best_pivot(unsigned i, unsigned j, T const & c_partial_pivoting, unsigned k) { unsigned queue_pivot_score = pivot_score_without_shortened_counters(i, j, k); for (unsigned ii = k; ii < dimension(); ii++) { - lean_assert(!can_improve_score_for_row(ii, queue_pivot_score, c_partial_pivoting, k)); + lp_assert(!can_improve_score_for_row(ii, queue_pivot_score, c_partial_pivoting, k)); } return true; } @@ -1026,7 +1026,7 @@ template bool sparse_matrix::pivot_queue_is_correct_for_row(unsigned i, unsigned k) { unsigned arow = adjust_row(i); for (auto & iv : m_rows[arow].m_values) { - lean_assert(pivot_score_without_shortened_counters(arow, iv.m_index, k + 1) == + lp_assert(pivot_score_without_shortened_counters(arow, iv.m_index, k + 1) == m_pivot_queue.get_priority(arow, iv.m_index)); } return true; @@ -1035,8 +1035,8 @@ bool sparse_matrix::pivot_queue_is_correct_for_row(unsigned i, unsigned k) template bool sparse_matrix::pivot_queue_is_correct_after_pivoting(int k) { for (unsigned i = k + 1; i < dimension(); i++ ) - lean_assert(pivot_queue_is_correct_for_row(i, k)); - lean_assert(m_pivot_queue.is_correct()); + lp_assert(pivot_queue_is_correct_for_row(i, k)); + lp_assert(m_pivot_queue.is_correct()); return true; } #endif @@ -1055,7 +1055,7 @@ bool sparse_matrix::get_pivot_for_column(unsigned &i, unsigned &j, int c_p #ifdef LEAN_DEBUG // if (!really_best_pivot(i, j, c_partial_pivoting, k)) { // print_active_matrix(k); - // lean_assert(false); + // lp_assert(false); // } #endif recover_pivot_queue(pivots_candidates_that_are_too_small); @@ -1088,7 +1088,7 @@ bool sparse_matrix::shorten_columns_by_pivot_row(unsigned i, unsigned pivo for (indexed_value & iv : row_chunk) { unsigned j = iv.m_index; if (j == pivot_column) { - lean_assert(!col_is_active(j)); + lp_assert(!col_is_active(j)); continue; } m_columns[j].shorten_markovich_by_one(); @@ -1151,11 +1151,11 @@ template bool sparse_matrix::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings & settings) const { for (unsigned i = 0; i < dimension(); i++) { vector> const & row_chunk = get_row_values(i); - lean_assert(row_chunk.size()); + lp_assert(row_chunk.size()); T const & max = abs(row_chunk[0].m_value); unsigned ai = adjust_row_inverse(i); for (auto & iv : row_chunk) { - lean_assert(abs(iv.m_value) <= max); + lp_assert(abs(iv.m_value) <= max); unsigned aj = adjust_column_inverse(iv.m_index); if (!(ai <= aj || numeric_traits::is_zero(iv.m_value))) return false; @@ -1193,18 +1193,18 @@ void sparse_matrix::check_column_vs_rows(unsigned col) { indexed_value & row_iv = column_iv_other(column_iv); if (row_iv.m_index != col) { // std::cout << "m_other in row does not belong to column " << col << ", but to column " << row_iv.m_index << std::endl; - lean_assert(false); + lp_assert(false); } if (& row_iv_other(row_iv) != &column_iv) { // std::cout << "row and col do not point to each other" << std::endl; - lean_assert(false); + lp_assert(false); } if (row_iv.m_value != column_iv.m_value) { // std::cout << "the data from col " << col << " for row " << column_iv.m_index << " is different in the column " << std::endl; // std::cout << "in the col it is " << column_iv.m_value << ", but in the row it is " << row_iv.m_value << std::endl; - lean_assert(false); + lp_assert(false); } } } @@ -1217,18 +1217,18 @@ void sparse_matrix::check_row_vs_columns(unsigned row) { if (column_iv.m_index != row) { // std::cout << "col_iv does not point to correct row " << row << " but to " << column_iv.m_index << std::endl; - lean_assert(false); + lp_assert(false); } if (& row_iv != & column_iv_other(column_iv)) { // std::cout << "row and col do not point to each other" << std::endl; - lean_assert(false); + lp_assert(false); } if (row_iv.m_value != column_iv.m_value) { // std::cout << "the data from col " << column_iv.m_index << " for row " << row << " is different in the column " << std::endl; // std::cout << "in the col it is " << column_iv.m_value << ", but in the row it is " << row_iv.m_value << std::endl; - lean_assert(false); + lp_assert(false); } } } diff --git a/src/util/lp/sparse_matrix_instances.cpp b/src/util/lp/sparse_matrix_instances.cpp index c06fcbf05..cf859a6a2 100644 --- a/src/util/lp/sparse_matrix_instances.cpp +++ b/src/util/lp/sparse_matrix_instances.cpp @@ -8,7 +8,7 @@ #include "util/lp/lu.h" #include "util/lp/sparse_matrix.hpp" #include "util/lp/dense_matrix.h" -namespace lean { +namespace lp { template double sparse_matrix::dot_product_with_row(unsigned int, vector const&) const; template void sparse_matrix::add_new_element(unsigned int, unsigned int, const double&); template void sparse_matrix::divide_row_by_constant(unsigned int, const double&, lp_settings&); @@ -24,7 +24,7 @@ template void sparse_matrix::remove_element(vector::replace_column(unsigned int, indexed_vector&, lp_settings&); template void sparse_matrix::set(unsigned int, unsigned int, double); template void sparse_matrix::set_max_in_row(vector >&); -template bool sparse_matrix::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); +template bool sparse_matrix::set_row_from_work_vector_and_clp_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); template bool sparse_matrix::shorten_active_matrix(unsigned int, eta_matrix*); template void sparse_matrix::solve_y_U(vector&) const; template sparse_matrix::sparse_matrix(static_matrix const&, vector&); @@ -41,7 +41,7 @@ template void sparse_matrix::prepare_for_factorization(); template void sparse_matrix::remove_element(vector> &, indexed_value&); template void sparse_matrix::replace_column(unsigned int, indexed_vector&, lp_settings&); template void sparse_matrix::set_max_in_row(vector>&); -template bool sparse_matrix::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); +template bool sparse_matrix::set_row_from_work_vector_and_clp_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); template bool sparse_matrix::shorten_active_matrix(unsigned int, eta_matrix*); template void sparse_matrix::solve_y_U(vector&) const; template sparse_matrix::sparse_matrix(static_matrix const&, vector&); @@ -57,7 +57,7 @@ template void sparse_matrix>::prepare_for_factorizati template void sparse_matrix>::remove_element(vector>&, indexed_value&); template void sparse_matrix>::replace_column(unsigned int, indexed_vector&, lp_settings&); template void sparse_matrix>::set_max_in_row(vector>&); -template bool sparse_matrix>::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); +template bool sparse_matrix>::set_row_from_work_vector_and_clp_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); template bool sparse_matrix>::shorten_active_matrix(unsigned int, eta_matrix >*); template void sparse_matrix>::solve_y_U(vector&) const; template sparse_matrix>::sparse_matrix(static_matrix > const&, vector&); @@ -65,37 +65,37 @@ template void sparse_matrix::double_solve_U_y(indexed_ve template void sparse_matrix::double_solve_U_y(indexed_vector&, const lp_settings&); template void sparse_matrix>::double_solve_U_y(indexed_vector&, const lp_settings&); template void sparse_matrix >::double_solve_U_y >(indexed_vector>&, const lp_settings&); -template void lean::sparse_matrix::solve_U_y_indexed_only(lean::indexed_vector&, const lp_settings&, vector &); -template void lean::sparse_matrix::solve_U_y_indexed_only(lean::indexed_vector&, const lp_settings &, vector &); +template void lp::sparse_matrix::solve_U_y_indexed_only(lp::indexed_vector&, const lp_settings&, vector &); +template void lp::sparse_matrix::solve_U_y_indexed_only(lp::indexed_vector&, const lp_settings &, vector &); #ifdef LEAN_DEBUG template bool sparse_matrix::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const; template bool sparse_matrix::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const; template bool sparse_matrix >::is_upper_triangular_and_maximums_are_set_correctly_in_rows(lp_settings&) const; #endif } -template void lean::sparse_matrix >::solve_U_y_indexed_only(lean::indexed_vector&, const lp_settings &, vector &); -template void lean::sparse_matrix::solve_U_y(vector&); -template void lean::sparse_matrix::double_solve_U_y(vector&); -template void lean::sparse_matrix::solve_U_y(vector&); -template void lean::sparse_matrix::double_solve_U_y(vector&); -template void lean::sparse_matrix >::solve_U_y >(vector >&); -template void lean::sparse_matrix >::double_solve_U_y >(vector >&); -template void lean::sparse_matrix::find_error_in_solution_U_y_indexed(lean::indexed_vector&, lean::indexed_vector&, const vector &); -template double lean::sparse_matrix::dot_product_with_row(unsigned int, lean::indexed_vector const&) const; -template void lean::sparse_matrix::find_error_in_solution_U_y_indexed(lean::indexed_vector&, lean::indexed_vector&, const vector &); -template lean::mpq lean::sparse_matrix::dot_product_with_row(unsigned int, lean::indexed_vector const&) const; -template void lean::sparse_matrix >::find_error_in_solution_U_y_indexed(lean::indexed_vector&, lean::indexed_vector&, const vector &); -template lean::mpq lean::sparse_matrix >::dot_product_with_row(unsigned int, lean::indexed_vector const&) const; -template void lean::sparse_matrix >::find_error_in_solution_U_y_indexed >(lean::indexed_vector >&, lean::indexed_vector >&, const vector &); -template lean::numeric_pair lean::sparse_matrix >::dot_product_with_row >(unsigned int, lean::indexed_vector > const&) const; -template void lean::sparse_matrix::extend_and_sort_active_rows(vector const&, vector&); +template void lp::sparse_matrix >::solve_U_y_indexed_only(lp::indexed_vector&, const lp_settings &, vector &); +template void lp::sparse_matrix::solve_U_y(vector&); +template void lp::sparse_matrix::double_solve_U_y(vector&); +template void lp::sparse_matrix::solve_U_y(vector&); +template void lp::sparse_matrix::double_solve_U_y(vector&); +template void lp::sparse_matrix >::solve_U_y >(vector >&); +template void lp::sparse_matrix >::double_solve_U_y >(vector >&); +template void lp::sparse_matrix::find_error_in_solution_U_y_indexed(lp::indexed_vector&, lp::indexed_vector&, const vector &); +template double lp::sparse_matrix::dot_product_with_row(unsigned int, lp::indexed_vector const&) const; +template void lp::sparse_matrix::find_error_in_solution_U_y_indexed(lp::indexed_vector&, lp::indexed_vector&, const vector &); +template lp::mpq lp::sparse_matrix::dot_product_with_row(unsigned int, lp::indexed_vector const&) const; +template void lp::sparse_matrix >::find_error_in_solution_U_y_indexed(lp::indexed_vector&, lp::indexed_vector&, const vector &); +template lp::mpq lp::sparse_matrix >::dot_product_with_row(unsigned int, lp::indexed_vector const&) const; +template void lp::sparse_matrix >::find_error_in_solution_U_y_indexed >(lp::indexed_vector >&, lp::indexed_vector >&, const vector &); +template lp::numeric_pair lp::sparse_matrix >::dot_product_with_row >(unsigned int, lp::indexed_vector > const&) const; +template void lp::sparse_matrix::extend_and_sort_active_rows(vector const&, vector&); -template void lean::sparse_matrix >::extend_and_sort_active_rows(vector const&, vector&); +template void lp::sparse_matrix >::extend_and_sort_active_rows(vector const&, vector&); -template void lean::sparse_matrix >::solve_U_y(vector&); -template void lean::sparse_matrix >::double_solve_U_y(vector&); -template void lean::sparse_matrix< lean::mpq,lean::numeric_pair< lean::mpq> >::set(unsigned int,unsigned int, lean::mpq); -template void lean::sparse_matrix::solve_y_U_indexed(lean::indexed_vector&, const lp_settings & ); -template void lean::sparse_matrix::solve_y_U_indexed(lean::indexed_vector&, const lp_settings &); -template void lean::sparse_matrix >::solve_y_U_indexed(lean::indexed_vector&, const lp_settings &); +template void lp::sparse_matrix >::solve_U_y(vector&); +template void lp::sparse_matrix >::double_solve_U_y(vector&); +template void lp::sparse_matrix< lp::mpq,lp::numeric_pair< lp::mpq> >::set(unsigned int,unsigned int, lp::mpq); +template void lp::sparse_matrix::solve_y_U_indexed(lp::indexed_vector&, const lp_settings & ); +template void lp::sparse_matrix::solve_y_U_indexed(lp::indexed_vector&, const lp_settings &); +template void lp::sparse_matrix >::solve_y_U_indexed(lp::indexed_vector&, const lp_settings &); diff --git a/src/util/lp/sparse_vector.h b/src/util/lp/sparse_vector.h index 975cb7f28..65bd6d3f3 100644 --- a/src/util/lp/sparse_vector.h +++ b/src/util/lp/sparse_vector.h @@ -9,7 +9,7 @@ #include "util/debug.h" #include "util/lp/lp_utils.h" #include "util/lp/lp_settings.h" -namespace lean { +namespace lp { template class sparse_vector { @@ -27,7 +27,7 @@ public: } #endif void divide(T const & a) { - lean_assert(!lp_settings::is_eps_small_general(a, 1e-12)); + lp_assert(!lp_settings::is_eps_small_general(a, 1e-12)); for (auto & t : m_data) { t.second /= a; } } diff --git a/src/util/lp/square_dense_submatrix.h b/src/util/lp/square_dense_submatrix.h index 019497aa5..5ffed7818 100644 --- a/src/util/lp/square_dense_submatrix.h +++ b/src/util/lp/square_dense_submatrix.h @@ -20,7 +20,7 @@ #include "util/lp/eta_matrix.h" #include "util/lp/binary_heap_upair_queue.h" #include "util/lp/sparse_matrix.h" -namespace lean { +namespace lp { template class square_dense_submatrix : public tail_matrix { // the submatrix uses the permutations of the parent matrix to access the elements @@ -30,11 +30,11 @@ class square_dense_submatrix : public tail_matrix { ref(unsigned i, square_dense_submatrix & s) : m_i_offset((i - s.m_index_start) * s.m_dim), m_s(s){} T & operator[] (unsigned j) { - lean_assert(j >= m_s.m_index_start); + lp_assert(j >= m_s.m_index_start); return m_s.m_v[m_i_offset + m_s.adjust_column(j) - m_s.m_index_start]; } const T & operator[] (unsigned j) const { - lean_assert(j >= m_s.m_index_start); + lp_assert(j >= m_s.m_index_start); return m_s.m_v[m_i_offset + m_s.adjust_column(j) - m_s.m_index_start]; } }; @@ -58,8 +58,8 @@ public: bool is_dense() const { return true; } ref operator[] (unsigned i) { - lean_assert(i >= m_index_start); - lean_assert(i < m_parent->dimension()); + lp_assert(i >= m_index_start); + lp_assert(i < m_parent->dimension()); return ref(i, *this); } @@ -148,7 +148,7 @@ public: } } } - lean_assert(wcopy.is_OK()); + lp_assert(wcopy.is_OK()); apply_from_right(w.m_data); w.m_index.clear(); if (numeric_traits::precise()) { @@ -167,11 +167,11 @@ public: } } #else - lean_assert(w.is_OK()); - lean_assert(m_work_vector.is_OK()); + lp_assert(w.is_OK()); + lp_assert(m_work_vector.is_OK()); m_work_vector.resize(w.data_size()); m_work_vector.clear(); - lean_assert(m_work_vector.is_OK()); + lp_assert(m_work_vector.is_OK()); unsigned end = m_index_start + m_dim; for (unsigned k : w.m_index) { // find j such that k = adjust_row_inverse(j) @@ -187,8 +187,8 @@ public: } } } - m_work_vector.clean_up(); - lean_assert(m_work_vector.is_OK()); + m_work_vector.clp_up(); + lp_assert(m_work_vector.is_OK()); w = m_work_vector; #endif } diff --git a/src/util/lp/square_dense_submatrix.hpp b/src/util/lp/square_dense_submatrix.hpp index 365c9d7f0..809d5c5a6 100644 --- a/src/util/lp/square_dense_submatrix.hpp +++ b/src/util/lp/square_dense_submatrix.hpp @@ -4,7 +4,7 @@ */ #include "util/vector.h" #include "util/lp/square_dense_submatrix.h" -namespace lean { +namespace lp { template square_dense_submatrix::square_dense_submatrix (sparse_matrix *parent_matrix, unsigned index_start) : m_index_start(index_start), @@ -18,7 +18,7 @@ square_dense_submatrix::square_dense_submatrix (sparse_matrix *paren unsigned row = parent_matrix->adjust_row(i); for (auto & iv : parent_matrix->get_row_values(row)) { unsigned j = parent_matrix->adjust_column_inverse(iv.m_index); - lean_assert(j>= m_index_start); + lp_assert(j>= m_index_start); m_v[row_offset + j] = iv.m_value; } row_offset += m_dim; @@ -43,7 +43,7 @@ template void square_dense_submatrix::init(sparse template int square_dense_submatrix::find_pivot_column_in_row(unsigned i) const { int j = -1; T max = zero_of_type(); - lean_assert(i >= m_index_start); + lp_assert(i >= m_index_start); unsigned row_start = (i - m_index_start) * m_dim; for (unsigned k = i; k < m_parent->dimension(); k++) { unsigned col = adjust_column(k); // this is where the column is in the row @@ -64,14 +64,14 @@ template void square_dense_submatrix::pivot(un } template void square_dense_submatrix::pivot_row_to_row(unsigned i, unsigned row, lp_settings & settings) { - lean_assert(i < row); + lp_assert(i < row); unsigned pj = adjust_column(i); // the pivot column unsigned pjd = pj - m_index_start; unsigned pivot_row_offset = (i-m_index_start)*m_dim; T pivot = m_v[pivot_row_offset + pjd]; unsigned row_offset= (row-m_index_start)*m_dim; T m = m_v[row_offset + pjd]; - lean_assert(!is_zero(pivot)); + lp_assert(!is_zero(pivot)); m_v[row_offset + pjd] = -m * pivot; // creating L matrix for (unsigned j = m_index_start; j < m_parent->dimension(); j++) { if (j == pj) { @@ -94,7 +94,7 @@ template void square_dense_submatrix::divide_r unsigned pj = adjust_column(i); // the pivot column unsigned irow_offset = (i - m_index_start) * m_dim; T pivot = m_v[irow_offset + pj - m_index_start]; - lean_assert(!is_zero(pivot)); + lp_assert(!is_zero(pivot)); for (unsigned k = m_index_start; k < m_parent->dimension(); k++) { if (k == pj){ m_v[irow_offset++] = one_of_type() / pivot; // creating the L matrix diagonal @@ -158,7 +158,7 @@ template void square_dense_submatrix::push_new template template L square_dense_submatrix::row_by_vector_product(unsigned i, const vector & v) { - lean_assert(i >= m_index_start); + lp_assert(i >= m_index_start); unsigned row_in_subm = i - m_index_start; unsigned row_offset = row_in_subm * m_dim; @@ -171,7 +171,7 @@ L square_dense_submatrix::row_by_vector_product(unsigned i, const vector template L square_dense_submatrix::column_by_vector_product(unsigned j, const vector & v) { - lean_assert(j >= m_index_start); + lp_assert(j >= m_index_start); unsigned offset = j - m_index_start; L r = zero_of_type(); @@ -182,7 +182,7 @@ L square_dense_submatrix::column_by_vector_product(unsigned j, const vecto template template L square_dense_submatrix::row_by_indexed_vector_product(unsigned i, const indexed_vector & v) { - lean_assert(i >= m_index_start); + lp_assert(i >= m_index_start); unsigned row_in_subm = i - m_index_start; unsigned row_offset = row_in_subm * m_dim; @@ -249,8 +249,8 @@ void square_dense_submatrix::apply_from_left_local(indexed_vector & w, #ifdef LEAN_DEBUG // cout << "w final" << endl; // print_vector(w.m_data); - // lean_assert(vectors_are_equal(deb_w, w.m_data)); - // lean_assert(w.is_OK()); + // lp_assert(vectors_are_equal(deb_w, w.m_data)); + // lp_assert(w.is_OK()); #endif } @@ -280,16 +280,16 @@ void square_dense_submatrix::apply_from_left_to_vector(vector & w) { #ifdef LEAN_DEBUG // cout << "w final" << endl; // print_vector(w.m_data); - // lean_assert(vectors_are_equal(deb_w, w)); + // lp_assert(vectors_are_equal(deb_w, w)); #endif } template bool square_dense_submatrix::is_L_matrix() const { #ifdef LEAN_DEBUG - lean_assert(m_row_permutation.is_identity()); + lp_assert(m_row_permutation.is_identity()); for (unsigned i = 0; i < m_parent->dimension(); i++) { if (i < m_index_start) { - lean_assert(m_column_permutation[i] == i); + lp_assert(m_column_permutation[i] == i); continue; } unsigned row_offs = (i-m_index_start)*m_dim; @@ -297,9 +297,9 @@ template bool square_dense_submatrix::is_L_mat unsigned j = m_index_start + k; unsigned jex = adjust_column_inverse(j); if (jex > i) { - lean_assert(is_zero(m_v[row_offs + k])); + lp_assert(is_zero(m_v[row_offs + k])); } else if (jex == i) { - lean_assert(!is_zero(m_v[row_offs + k])); + lp_assert(!is_zero(m_v[row_offs + k])); } } } @@ -327,7 +327,7 @@ template void square_dense_submatrix::apply_from_ } w = t; #ifdef LEAN_DEBUG - // lean_assert(vector_are_equal(deb_w, w)); + // lp_assert(vector_are_equal(deb_w, w)); #endif } diff --git a/src/util/lp/square_dense_submatrix_instances.cpp b/src/util/lp/square_dense_submatrix_instances.cpp index 7d45aaaa1..7283bb3da 100644 --- a/src/util/lp/square_dense_submatrix_instances.cpp +++ b/src/util/lp/square_dense_submatrix_instances.cpp @@ -5,29 +5,29 @@ #include #include "util/vector.h" #include "util/lp/square_dense_submatrix.hpp" -template void lean::square_dense_submatrix::init(lean::sparse_matrix*, unsigned int); -template lean::square_dense_submatrix::square_dense_submatrix(lean::sparse_matrix*, unsigned int); -template void lean::square_dense_submatrix::update_parent_matrix(lean::lp_settings&); -template bool lean::square_dense_submatrix::is_L_matrix() const; -template void lean::square_dense_submatrix::conjugate_by_permutation(lean::permutation_matrix&); -template int lean::square_dense_submatrix::find_pivot_column_in_row(unsigned int) const; -template void lean::square_dense_submatrix::pivot(unsigned int, lean::lp_settings&); -template lean::square_dense_submatrix >::square_dense_submatrix(lean::sparse_matrix >*, unsigned int); -template void lean::square_dense_submatrix >::update_parent_matrix(lean::lp_settings&); -template bool lean::square_dense_submatrix >::is_L_matrix() const; -template void lean::square_dense_submatrix >::conjugate_by_permutation(lean::permutation_matrix >&); -template int lean::square_dense_submatrix >::find_pivot_column_in_row(unsigned int) const; -template void lean::square_dense_submatrix >::pivot(unsigned int, lean::lp_settings&); +template void lp::square_dense_submatrix::init(lp::sparse_matrix*, unsigned int); +template lp::square_dense_submatrix::square_dense_submatrix(lp::sparse_matrix*, unsigned int); +template void lp::square_dense_submatrix::update_parent_matrix(lp::lp_settings&); +template bool lp::square_dense_submatrix::is_L_matrix() const; +template void lp::square_dense_submatrix::conjugate_by_permutation(lp::permutation_matrix&); +template int lp::square_dense_submatrix::find_pivot_column_in_row(unsigned int) const; +template void lp::square_dense_submatrix::pivot(unsigned int, lp::lp_settings&); +template lp::square_dense_submatrix >::square_dense_submatrix(lp::sparse_matrix >*, unsigned int); +template void lp::square_dense_submatrix >::update_parent_matrix(lp::lp_settings&); +template bool lp::square_dense_submatrix >::is_L_matrix() const; +template void lp::square_dense_submatrix >::conjugate_by_permutation(lp::permutation_matrix >&); +template int lp::square_dense_submatrix >::find_pivot_column_in_row(unsigned int) const; +template void lp::square_dense_submatrix >::pivot(unsigned int, lp::lp_settings&); #ifdef LEAN_DEBUG -template double lean::square_dense_submatrix::get_elem(unsigned int, unsigned int) const; +template double lp::square_dense_submatrix::get_elem(unsigned int, unsigned int) const; #endif -template void lean::square_dense_submatrix::apply_from_right(vector&); +template void lp::square_dense_submatrix::apply_from_right(vector&); -template void lean::square_dense_submatrix::apply_from_left_local(lean::indexed_vector&, lean::lp_settings&); -template void lean::square_dense_submatrix::apply_from_left_to_vector(vector&); -template lean::square_dense_submatrix::square_dense_submatrix(lean::sparse_matrix*, unsigned int); -template void lean::square_dense_submatrix::update_parent_matrix(lean::lp_settings&); -template bool lean::square_dense_submatrix::is_L_matrix() const; -template void lean::square_dense_submatrix::conjugate_by_permutation(lean::permutation_matrix&); -template int lean::square_dense_submatrix::find_pivot_column_in_row(unsigned int) const; -template void lean::square_dense_submatrix::pivot(unsigned int, lean::lp_settings&); +template void lp::square_dense_submatrix::apply_from_left_local(lp::indexed_vector&, lp::lp_settings&); +template void lp::square_dense_submatrix::apply_from_left_to_vector(vector&); +template lp::square_dense_submatrix::square_dense_submatrix(lp::sparse_matrix*, unsigned int); +template void lp::square_dense_submatrix::update_parent_matrix(lp::lp_settings&); +template bool lp::square_dense_submatrix::is_L_matrix() const; +template void lp::square_dense_submatrix::conjugate_by_permutation(lp::permutation_matrix&); +template int lp::square_dense_submatrix::find_pivot_column_in_row(unsigned int) const; +template void lp::square_dense_submatrix::pivot(unsigned int, lp::lp_settings&); diff --git a/src/util/lp/stacked_map.h b/src/util/lp/stacked_map.h index 4692540dd..1c55b9f9f 100644 --- a/src/util/lp/stacked_map.h +++ b/src/util/lp/stacked_map.h @@ -8,7 +8,7 @@ #include #include #include -namespace lean { +namespace lp { template second; } }; @@ -73,7 +73,7 @@ public: const B & operator[]( const A & a) const { auto it = m_map.find(a); if (it == m_map.end()) { - lean_assert(false); + lp_assert(false); } return it->second; @@ -128,7 +128,7 @@ public: for (auto & t: d.m_original_changed) { m_map[t.first] = t.second; } - // lean_assert(d.m_deb_copy == m_map); + // lp_assert(d.m_deb_copy == m_map); m_stack.pop(); } } @@ -142,7 +142,7 @@ public: delta & d = m_stack.top(); auto it = m_map.find(key); if (it == m_map.end()) { - lean_assert(d.m_new.find(key) == d.m_new.end()); + lp_assert(d.m_new.find(key) == d.m_new.end()); return; } auto &orig_changed = d.m_original_changed; @@ -151,7 +151,7 @@ public: if (orig_changed.find(key) == orig_changed.end()) orig_changed.emplace(it->first, it->second); // need to restore } else { // k is new - lean_assert(orig_changed.find(key) == orig_changed.end()); + lp_assert(orig_changed.find(key) == orig_changed.end()); d.m_new.erase(nit); } diff --git a/src/util/lp/stacked_unordered_set.h b/src/util/lp/stacked_unordered_set.h index 69c4cf03b..88bb3160c 100644 --- a/src/util/lp/stacked_unordered_set.h +++ b/src/util/lp/stacked_unordered_set.h @@ -8,7 +8,7 @@ #include #include #include -namespace lean { +namespace lp { template , @@ -81,7 +81,7 @@ public: for (auto & t : d.m_erased) { m_set.insert(t); } - lean_assert(d.m_deb_copy == m_set); + lp_assert(d.m_deb_copy == m_set); m_stack.pop(); } } diff --git a/src/util/lp/stacked_value.h b/src/util/lp/stacked_value.h index 2a1e85be7..8cd43afce 100644 --- a/src/util/lp/stacked_value.h +++ b/src/util/lp/stacked_value.h @@ -6,7 +6,7 @@ #pragma once // add to value the stack semantics #include -namespace lean { +namespace lp { template class stacked_value { T m_value; std::stack m_stack; diff --git a/src/util/lp/stacked_vector.h b/src/util/lp/stacked_vector.h index 14b0d0141..4ed6f44d9 100644 --- a/src/util/lp/stacked_vector.h +++ b/src/util/lp/stacked_vector.h @@ -7,7 +7,7 @@ Author: Lev Nachmanson #include #include #include "util/vector.h" -namespace lean { +namespace lp { template < typename B> class stacked_vector { vector m_stack_of_vector_sizes; vector m_stack_of_change_sizes; @@ -19,7 +19,7 @@ public: unsigned m_i; public: ref(stacked_vector &m, unsigned key) :m_vec(m), m_i(key) { - lean_assert(key < m.size()); + lp_assert(key < m.size()); } ref & operator=(const B & b) { m_vec.emplace_replace(m_i, b); @@ -43,7 +43,7 @@ public: unsigned m_i; public: ref_const(const stacked_vector &m, unsigned key) :m_vec(m), m_i(key) { - lean_assert(key < m.size()); + lp_assert(key < m.size()); } operator const B&() const { @@ -71,7 +71,7 @@ public: /* const B & operator[](unsigned a) const { - lean_assert(a < m_vector.size()); + lp_assert(a < m_vector.size()); return m_vector[a]; } */ @@ -91,7 +91,7 @@ public: template void pop_tail(vector & v, unsigned k) { - lean_assert(v.size() >= k); + lp_assert(v.size() >= k); v.resize(v.size() - k); } @@ -101,8 +101,8 @@ public: } void pop(unsigned k) { - lean_assert(m_stack_of_vector_sizes.size() >= k); - lean_assert(k > 0); + lp_assert(m_stack_of_vector_sizes.size() >= k); + lp_assert(k > 0); resize(m_vector, m_stack_of_vector_sizes[m_stack_of_vector_sizes.size() - k]); pop_tail(m_stack_of_vector_sizes, k); unsigned first_change = m_stack_of_change_sizes[m_stack_of_change_sizes.size() - k]; @@ -122,15 +122,15 @@ public: return; delta & d = m_stack.back(); - lean_assert(m_vector.size() >= d.m_size); + lp_assert(m_vector.size() >= d.m_size); while (m_vector.size() > d.m_size) m_vector.pop_back(); for (auto & t : d.m_original_changed) { - lean_assert(t.first < m_vector.size()); + lp_assert(t.first < m_vector.size()); m_vector[t.first] = t.second; } - // lean_assert(d.m_deb_copy == m_vector); + // lp_assert(d.m_deb_copy == m_vector); m_stack.pop_back();*/ } @@ -160,7 +160,7 @@ public: } unsigned peek_size(unsigned k) const { - lean_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]; } diff --git a/src/util/lp/static_matrix.h b/src/util/lp/static_matrix.h index 5ef4b449f..f1d7f064b 100644 --- a/src/util/lp/static_matrix.h +++ b/src/util/lp/static_matrix.h @@ -13,7 +13,7 @@ #include "util/lp/permutation_matrix.h" #include "util/lp/linear_combination_iterator.h" #include -namespace lean { +namespace lp { struct column_cell { unsigned m_i; // points to the row @@ -193,7 +193,7 @@ public: void scan_row_to_work_vector(unsigned i); - void clean_row_work_vector(unsigned i); + void clp_row_work_vector(unsigned i); #ifdef LEAN_DEBUG @@ -203,7 +203,7 @@ public: virtual void set_number_of_columns(unsigned /*n*/) { } #endif - T get_max_val_in_row(unsigned /* i */) const { lean_unreachable(); } + T get_max_val_in_row(unsigned /* i */) const { lp_unreachable(); } T get_balance() const; @@ -219,7 +219,7 @@ public: for (auto & c : row) { unsigned j = c.m_j; auto & col = m_columns[j]; - lean_assert(col[col.size() - 1].m_i == m_rows.size() -1 ); // todo : start here!!!! + lp_assert(col[col.size() - 1].m_i == m_rows.size() -1 ); // todo : start here!!!! col.pop_back(); } } @@ -246,7 +246,7 @@ public: m_columns.pop_back(); // delete the last column m_stack.pop(); } - lean_assert(is_correct()); + lp_assert(is_correct()); } void multiply_row(unsigned row, T const & alpha) { @@ -262,7 +262,7 @@ public: } T dot_product_with_column(const vector & y, unsigned j) const { - lean_assert(j < column_count()); + lp_assert(j < column_count()); T ret = numeric_traits::zero(); for (auto & it : m_columns[j]) { ret += y[it.m_i] * get_val(it); // get_value_of_column_cell(it); @@ -281,20 +281,20 @@ public: // now fix the columns for (auto & rc : m_rows[i]) { column_cell & cc = m_columns[rc.m_j][rc.m_offset]; - lean_assert(cc.m_i == ii); + lp_assert(cc.m_i == ii); cc.m_i = i; } for (auto & rc : m_rows[ii]) { column_cell & cc = m_columns[rc.m_j][rc.m_offset]; - lean_assert(cc.m_i == i); + lp_assert(cc.m_i == i); cc.m_i = ii; } } void fill_last_row_with_pivoting(linear_combination_iterator & it, const vector & basis_heading) { - lean_assert(numeric_traits::precise()); - lean_assert(row_count() > 0); + lp_assert(numeric_traits::precise()); + lp_assert(row_count() > 0); m_work_vector.resize(column_count()); T a; unsigned j; @@ -332,13 +332,13 @@ public: alpha = zero_of_type(); m_work_vector.erase_from_index(j); } - lean_assert(m_work_vector.is_OK()); + lp_assert(m_work_vector.is_OK()); unsigned last_row = row_count() - 1; for (unsigned j : m_work_vector.m_index) { set (last_row, j, m_work_vector.m_data[j]); } - lean_assert(column_count() > 0); + lp_assert(column_count() > 0); set(last_row, column_count() - 1, one_of_type()); } @@ -354,7 +354,7 @@ public: template L dot_product_with_row(unsigned row, const vector & w) const { L ret = zero_of_type(); - lean_assert(row < m_rows.size()); + lp_assert(row < m_rows.size()); for (auto & it : m_rows[row]) { ret += w[it.m_j] * it.get_val(); } diff --git a/src/util/lp/static_matrix.hpp b/src/util/lp/static_matrix.hpp index fb12da8c4..a3f69c9bf 100644 --- a/src/util/lp/static_matrix.hpp +++ b/src/util/lp/static_matrix.hpp @@ -6,11 +6,11 @@ #include #include #include "util/lp/static_matrix.h" -namespace lean { +namespace lp { // each assignment for this matrix should be issued only once!!! template void static_matrix::init_row_columns(unsigned m, unsigned n) { - lean_assert(m_rows.size() == 0 && m_columns.size() == 0); + lp_assert(m_rows.size() == 0 && m_columns.size() == 0); for (unsigned i = 0; i < m; i++){ m_rows.push_back(row_strip()); } @@ -30,23 +30,23 @@ template void static_matrix::scan_row_ii_to_offse template bool static_matrix::pivot_row_to_row_given_cell(unsigned i, column_cell & c, unsigned pivot_col) { unsigned ii = c.m_i; - lean_assert(i < row_count() && ii < column_count()); - lean_assert(i != ii); + lp_assert(i < row_count() && ii < column_count()); + lp_assert(i != ii); m_became_zeros.reset(); T alpha = -get_val(c); - lean_assert(!is_zero(alpha)); + lp_assert(!is_zero(alpha)); auto & ii_row_vals = m_rows[ii]; remove_element(ii_row_vals, ii_row_vals[c.m_offset]); scan_row_ii_to_offset_vector(ii); - lean_assert(!is_zero(alpha)); + lp_assert(!is_zero(alpha)); unsigned prev_size_ii = ii_row_vals.size(); // run over the pivot row and update row ii for (const auto & iv : m_rows[i]) { unsigned j = iv.m_j; if (j == pivot_col) continue; T alv = alpha * iv.m_value; - lean_assert(!is_zero(iv.m_value)); + lp_assert(!is_zero(iv.m_value)); int j_offs = m_vector_of_row_offsets[j]; if (j_offs == -1) { // it is a new element add_new_element(ii, j, alv); @@ -61,7 +61,7 @@ template bool static_matrix::pivot_row_to_row_giv } } - // clean the work vector + // clp the work vector for (unsigned k = 0; k < prev_size_ii; k++) { m_vector_of_row_offsets[ii_row_vals[k].m_j] = -1; } @@ -104,9 +104,9 @@ template void static_matrix::init_empty_matrix } template unsigned static_matrix::lowest_row_in_column(unsigned col) { - lean_assert(col < column_count()); + lp_assert(col < column_count()); column_strip & colstrip = m_columns[col]; - lean_assert(colstrip.size() > 0); + lp_assert(colstrip.size() > 0); unsigned ret = 0; for (auto & t : colstrip) { if (t.m_i > ret) { @@ -122,7 +122,7 @@ template void static_matrix::add_columns_at_th } template void static_matrix::forget_last_columns(unsigned how_many_to_forget) { - lean_assert(m_columns.size() >= how_many_to_forget); + lp_assert(m_columns.size() >= how_many_to_forget); unsigned j = column_count() - 1; for (; how_many_to_forget > 0; how_many_to_forget--) { remove_last_column(j --); @@ -151,7 +151,7 @@ template void static_matrix::remove_last_column(u template void static_matrix::set(unsigned row, unsigned col, T const & val) { if (numeric_traits::is_zero(val)) return; - lean_assert(row < row_count() && col < column_count()); + lp_assert(row < row_count() && col < column_count()); auto & r = m_rows[row]; unsigned offs_in_cols = static_cast(m_columns[col].size()); m_columns[col].push_back(make_column_cell(row, static_cast(r.size()))); @@ -171,7 +171,7 @@ std::set> static_matrix::get_domain() { template void static_matrix::copy_column_to_indexed_vector (unsigned j, indexed_vector & v) const { - lean_assert(j < m_columns.size()); + lp_assert(j < m_columns.size()); for (auto & it : m_columns[j]) { const T& val = get_val(it); if (!is_zero(val)) @@ -240,7 +240,7 @@ template void static_matrix::check_consistency for (int i = 0; i < m_rows.size(); i++){ for (auto & t : m_rows[i]) { std::pair p(i, t.m_j); - lean_assert(by_rows.find(p) == by_rows.end()); + lp_assert(by_rows.find(p) == by_rows.end()); by_rows[p] = t.get_val(); } } @@ -248,11 +248,11 @@ template void static_matrix::check_consistency for (int i = 0; i < m_columns.size(); i++){ for (auto & t : m_columns[i]) { std::pair p(t.m_i, i); - lean_assert(by_cols.find(p) == by_cols.end()); + lp_assert(by_cols.find(p) == by_cols.end()); by_cols[p] = get_val(t); } } - lean_assert(by_rows.size() == by_cols.size()); + lp_assert(by_rows.size() == by_cols.size()); for (auto & t : by_rows) { auto ic = by_cols.find(t.first); @@ -260,8 +260,8 @@ template void static_matrix::check_consistency //std::cout << "rows have pair (" << t.first.first <<"," << t.first.second // << "), but columns don't " << std::endl; } - lean_assert(ic != by_cols.end()); - lean_assert(t.second == ic->second); + lp_assert(ic != by_cols.end()); + lp_assert(t.second == ic->second); } } #endif diff --git a/src/util/lp/static_matrix_instances.cpp b/src/util/lp/static_matrix_instances.cpp index 59905929e..263021239 100644 --- a/src/util/lp/static_matrix_instances.cpp +++ b/src/util/lp/static_matrix_instances.cpp @@ -13,7 +13,7 @@ #include "util/lp/lp_primal_core_solver.h" #include "util/lp/scaler.h" #include "util/lp/lar_solver.h" -namespace lean { +namespace lp { template void static_matrix::add_columns_at_the_end(unsigned int); template void static_matrix::clear(); #ifdef LEAN_DEBUG @@ -23,8 +23,8 @@ template void static_matrix::copy_column_to_indexed_vector(unsig template double static_matrix::get_balance() const; template std::set> static_matrix::get_domain(); -template std::set> lean::static_matrix::get_domain(); -template std::set> lean::static_matrix >::get_domain(); +template std::set> lp::static_matrix::get_domain(); +template std::set> lp::static_matrix >::get_domain(); template double static_matrix::get_elem(unsigned int, unsigned int) const; template double static_matrix::get_max_abs_in_column(unsigned int) const; template double static_matrix::get_min_abs_in_column(unsigned int) const; @@ -60,10 +60,10 @@ template void static_matrix >::init_empty_matrix(unsigned template void static_matrix >::set(unsigned int, unsigned int, mpq const&); -template bool lean::static_matrix::pivot_row_to_row_given_cell(unsigned int, column_cell &, unsigned int); -template bool lean::static_matrix::pivot_row_to_row_given_cell(unsigned int, column_cell& , unsigned int); -template bool lean::static_matrix >::pivot_row_to_row_given_cell(unsigned int, column_cell&, unsigned int); -template void lean::static_matrix >::remove_element(vector, true, unsigned int>&, lean::row_cell&); +template bool lp::static_matrix::pivot_row_to_row_given_cell(unsigned int, column_cell &, unsigned int); +template bool lp::static_matrix::pivot_row_to_row_given_cell(unsigned int, column_cell& , unsigned int); +template bool lp::static_matrix >::pivot_row_to_row_given_cell(unsigned int, column_cell&, unsigned int); +template void lp::static_matrix >::remove_element(vector, true, unsigned int>&, lp::row_cell&); } diff --git a/src/util/lp/tail_matrix.h b/src/util/lp/tail_matrix.h index c337b0933..0e9c6320a 100644 --- a/src/util/lp/tail_matrix.h +++ b/src/util/lp/tail_matrix.h @@ -10,7 +10,7 @@ #include "util/lp/lp_settings.h" // These matrices appear at the end of the list -namespace lean { +namespace lp { template class tail_matrix #ifdef LEAN_DEBUG diff --git a/src/util/lp/test_bound_analyzer.h b/src/util/lp/test_bound_analyzer.h index 262c610c7..43ba244dc 100644 --- a/src/util/lp/test_bound_analyzer.h +++ b/src/util/lp/test_bound_analyzer.h @@ -16,7 +16,7 @@ // In the same loop trying to pin variables by pushing the partial sum up, denoting the variable related to it by _l // here in addition we assume that all coefficient in the row are positive -namespace lean { +namespace lp { class test_bound_analyzer { linear_combination_iterator & m_it; @@ -74,7 +74,7 @@ public : void analyze_i_for_upper(unsigned i) { mpq l; bool strict = false; - lean_assert(is_zero(l)); + lp_assert(is_zero(l)); for (unsigned k = 0; k < m_index.size(); k++) { if (k == i) continue; @@ -165,7 +165,7 @@ public : void analyze_i_for_lower(unsigned i) { mpq l; - lean_assert(is_zero(l)); + lp_assert(is_zero(l)); bool strict = false; for (unsigned k = 0; k < m_index.size(); k++) { if (k == i) diff --git a/src/util/lp/ul_pair.h b/src/util/lp/ul_pair.h index 2e77a7db0..1df20aa56 100644 --- a/src/util/lp/ul_pair.h +++ b/src/util/lp/ul_pair.h @@ -10,7 +10,7 @@ #include #include "util/lp/column_info.h" -namespace lean { +namespace lp { enum lconstraint_kind { LE = -2, LT = -1 , GE = 2, GT = 1, EQ = 0 From 86ed01a63b416d74e101ecab781bbedc0d80356c Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 10 Jul 2017 11:30:08 -0700 Subject: [PATCH 134/159] replace clp to clean Signed-off-by: Lev Nachmanson --- src/util/lp/indexed_vector.h | 4 ++-- src/util/lp/lar_solver.cpp | 17 +++++++---------- src/util/lp/lar_solver.h | 4 ++-- src/util/lp/lp_dual_simplex.hpp | 2 +- src/util/lp/lp_primal_simplex.hpp | 2 +- src/util/lp/lp_solver.h | 2 +- src/util/lp/lp_solver.hpp | 2 +- src/util/lp/lp_solver_instances.cpp | 4 ++-- src/util/lp/lu.hpp | 8 ++++---- src/util/lp/sparse_matrix.h | 4 ++-- src/util/lp/sparse_matrix.hpp | 8 ++++---- src/util/lp/sparse_matrix_instances.cpp | 6 +++--- src/util/lp/square_dense_submatrix.h | 2 +- src/util/lp/static_matrix.h | 2 +- src/util/lp/static_matrix.hpp | 2 +- 15 files changed, 33 insertions(+), 36 deletions(-) diff --git a/src/util/lp/indexed_vector.h b/src/util/lp/indexed_vector.h index 0e013f778..6c0c32414 100644 --- a/src/util/lp/indexed_vector.h +++ b/src/util/lp/indexed_vector.h @@ -86,7 +86,7 @@ public: return m_data[i]; } - void clp_up() { + void clean_up() { #if 0==1 for (unsigned k = 0; k < m_index.size(); k++) { unsigned i = m_index[k]; @@ -140,7 +140,7 @@ public: } } - void restore_index_and_clp_from_data() { + void restore_index_and_clean_from_data() { m_index.resize(0); for (unsigned i = 0; i < m_data.size(); i++) { T & v = m_data[i]; diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index 3e7c994e6..93cd6a118 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -316,9 +316,6 @@ void lar_solver::fill_explanation_from_infeasible_column(vector lar_solver::get_list_of_all_var_indices() const { vector ret; for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_heading.size(); j++) @@ -338,7 +335,7 @@ void lar_solver::push() { m_constraint_count.push(); } -void lar_solver::clp_large_elements_after_pop(unsigned n, int_set& set) { +void lar_solver::clean_large_elements_after_pop(unsigned n, int_set& set) { vector to_remove; for (unsigned j: set.m_index) if (j >= n) @@ -348,7 +345,7 @@ void lar_solver::clp_large_elements_after_pop(unsigned n, int_set& set) { } void lar_solver::shrink_inf_set_after_pop(unsigned n, int_set & set) { - clp_large_elements_after_pop(n, set); + clean_large_elements_after_pop(n, set); set.resize(n); } @@ -367,10 +364,10 @@ void lar_solver::pop(unsigned k) { m_vars_to_ul_pairs.pop(k); m_mpq_lar_core_solver.pop(k); - clp_large_elements_after_pop(n, m_columns_with_changed_bound); + clean_large_elements_after_pop(n, m_columns_with_changed_bound); unsigned m = A_r().row_count(); - clp_large_elements_after_pop(m, m_rows_with_changed_bounds); - clp_inf_set_of_r_solver_after_pop(); + clean_large_elements_after_pop(m, m_rows_with_changed_bounds); + clean_inf_set_of_r_solver_after_pop(); lp_assert(m_settings.simplex_strategy() == simplex_strategy_enum::undecided || (!use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); @@ -1346,9 +1343,9 @@ void lar_solver::pop_tableau() { lp_assert(m_mpq_lar_core_solver.m_r_solver.basis_heading_is_correct()); } -void lar_solver::clp_inf_set_of_r_solver_after_pop() { +void lar_solver::clean_inf_set_of_r_solver_after_pop() { vector became_feas; - clp_large_elements_after_pop(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.m_inf_set); + clean_large_elements_after_pop(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.m_inf_set); std::unordered_set basic_columns_with_changed_cost; auto inf_index_copy = m_mpq_lar_core_solver.m_r_solver.m_inf_set.m_index; for (auto j: inf_index_copy) { diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index 0961d2b8d..1a12a5953 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -222,7 +222,7 @@ public: vector get_list_of_all_var_indices() const; void push(); - static void clp_large_elements_after_pop(unsigned n, int_set& set); + static void clean_large_elements_after_pop(unsigned n, int_set& set); static void shrink_inf_set_after_pop(unsigned n, int_set & set); @@ -403,7 +403,7 @@ public: void remove_last_column_from_basis_tableau(unsigned j); void remove_column_from_tableau(unsigned j); void pop_tableau(); - void clp_inf_set_of_r_solver_after_pop(); + void clean_inf_set_of_r_solver_after_pop(); void shrink_explanation_to_minimum(vector> & explanation) const; diff --git a/src/util/lp/lp_dual_simplex.hpp b/src/util/lp/lp_dual_simplex.hpp index 8e16853a8..5a585c68e 100644 --- a/src/util/lp/lp_dual_simplex.hpp +++ b/src/util/lp/lp_dual_simplex.hpp @@ -335,7 +335,7 @@ template void lp_dual_simplex::find_maximal_solut this->flip_costs(); // do it for now, todo ( remove the flipping) - this->clpup(); + this->cleanup(); if (this->m_status == INFEASIBLE) { return; } diff --git a/src/util/lp/lp_primal_simplex.hpp b/src/util/lp/lp_primal_simplex.hpp index 76ed5684c..a09cd714f 100644 --- a/src/util/lp/lp_primal_simplex.hpp +++ b/src/util/lp/lp_primal_simplex.hpp @@ -157,7 +157,7 @@ template void lp_primal_simplex::find_maximal_sol return; } - this->clpup(); + this->cleanup(); this->fill_matrix_A_and_init_right_side(); if (this->m_status == lp_status::INFEASIBLE) { return; diff --git a/src/util/lp/lp_solver.h b/src/util/lp/lp_solver.h index 984e818e1..6c878c687 100644 --- a/src/util/lp/lp_solver.h +++ b/src/util/lp/lp_solver.h @@ -205,7 +205,7 @@ protected: unsigned try_to_remove_some_rows(); - void clpup(); + void cleanup(); void map_external_rows_to_core_solver_rows(); diff --git a/src/util/lp/lp_solver.hpp b/src/util/lp/lp_solver.hpp index 46674cf5e..a903421fd 100644 --- a/src/util/lp/lp_solver.hpp +++ b/src/util/lp/lp_solver.hpp @@ -381,7 +381,7 @@ template unsigned lp_solver::try_to_remove_some_r return static_cast(rows_to_delete.size()); } -template void lp_solver::clpup() { +template void lp_solver::cleanup() { int n = 0; // number of deleted rows int d; while ((d = try_to_remove_some_rows() > 0)) diff --git a/src/util/lp/lp_solver_instances.cpp b/src/util/lp/lp_solver_instances.cpp index 6e62ba7d3..dce86914c 100644 --- a/src/util/lp/lp_solver_instances.cpp +++ b/src/util/lp/lp_solver_instances.cpp @@ -5,7 +5,7 @@ #include #include "util/lp/lp_solver.hpp" template void lp::lp_solver::add_constraint(lp::lp_relation, double, unsigned int); -template void lp::lp_solver::clpup(); +template void lp::lp_solver::cleanup(); template void lp::lp_solver::count_slacks_and_artificials(); template void lp::lp_solver::fill_m_b(); template void lp::lp_solver::fill_matrix_A_and_init_right_side(); @@ -21,7 +21,7 @@ template void lp::lp_solver::scale(); template void lp::lp_solver::set_scaled_cost(unsigned int); template lp::lp_solver::~lp_solver(); template void lp::lp_solver::add_constraint(lp::lp_relation, lp::mpq, unsigned int); -template void lp::lp_solver::clpup(); +template void lp::lp_solver::cleanup(); template void lp::lp_solver::count_slacks_and_artificials(); template void lp::lp_solver::fill_m_b(); template void lp::lp_solver::fill_matrix_A_and_init_right_side(); diff --git a/src/util/lp/lu.hpp b/src/util/lp/lu.hpp index c602892ac..64ac8efe2 100644 --- a/src/util/lp/lu.hpp +++ b/src/util/lp/lu.hpp @@ -415,7 +415,7 @@ void lu::solve_yB_with_error_check_indexed(indexed_vector & y, const ve solve_yB_indexed(y); } else { solve_yB(y.m_data); - y.restore_index_and_clp_from_data(); + y.restore_index_and_clean_from_data(); } return; } @@ -429,7 +429,7 @@ void lu::solve_yB_with_error_check_indexed(indexed_vector & y, const ve find_error_of_yB(m_y_copy.m_data, y.m_data, basis); solve_yB(m_y_copy.m_data); add_delta_to_solution(m_y_copy.m_data, y.m_data); - y.restore_index_and_clp_from_data(); + y.restore_index_and_clean_from_data(); m_y_copy.clear_all(); } else { find_error_of_yB_indexed(y, heading, settings); // this works with m_y_copy @@ -439,7 +439,7 @@ void lu::solve_yB_with_error_check_indexed(indexed_vector & y, const ve lp_assert(m_y_copy.is_OK()); } else { solve_yB_with_error_check(y.m_data, basis); - y.restore_index_and_clp_from_data(); + y.restore_index_and_clean_from_data(); } } @@ -894,7 +894,7 @@ void lu::calculate_Lwave_Pwave_for_bump(unsigned replaced_column, unsigned if (replaced_column < lowest_row_of_the_bump) { diagonal_elem = m_row_eta_work_vector[lowest_row_of_the_bump]; // lp_assert(m_row_eta_work_vector.is_OK()); - m_U.set_row_from_work_vector_and_clp_work_vector_not_adjusted(m_U.adjust_row(lowest_row_of_the_bump), m_row_eta_work_vector, m_settings); + m_U.set_row_from_work_vector_and_clean_work_vector_not_adjusted(m_U.adjust_row(lowest_row_of_the_bump), m_row_eta_work_vector, m_settings); } else { diagonal_elem = m_U(lowest_row_of_the_bump, lowest_row_of_the_bump); // todo - get it more efficiently } diff --git a/src/util/lp/sparse_matrix.h b/src/util/lp/sparse_matrix.h index 0fc84f8f5..17f9ed7e0 100644 --- a/src/util/lp/sparse_matrix.h +++ b/src/util/lp/sparse_matrix.h @@ -190,13 +190,13 @@ public: // set the max val as well // returns false if the resulting row is all zeroes, and true otherwise - bool set_row_from_work_vector_and_clp_work_vector_not_adjusted(unsigned i0, indexed_vector & work_vec, + bool set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned i0, indexed_vector & work_vec, lp_settings & settings); // set the max val as well // returns false if the resulting row is all zeroes, and true otherwise - bool set_row_from_work_vector_and_clp_work_vector(unsigned i0); + bool set_row_from_work_vector_and_clean_work_vector(unsigned i0); void remove_zero_elements_and_set_data_on_existing_elements(unsigned row); diff --git a/src/util/lp/sparse_matrix.hpp b/src/util/lp/sparse_matrix.hpp index 175633eda..a26f36ae9 100644 --- a/src/util/lp/sparse_matrix.hpp +++ b/src/util/lp/sparse_matrix.hpp @@ -296,7 +296,7 @@ bool sparse_matrix::pivot_row_to_row(unsigned i, const T& alpha, unsigned } - // clp the work vector + // clean the work vector for (unsigned k = 0; k < prev_size_i0; k++) { m_work_pivot_vector[i0_row_vals[k].m_index] = -1; } @@ -319,7 +319,7 @@ bool sparse_matrix::pivot_row_to_row(unsigned i, const T& alpha, unsigned // set the max val as well // returns false if the resulting row is all zeroes, and true otherwise template -bool sparse_matrix::set_row_from_work_vector_and_clp_work_vector_not_adjusted(unsigned i0, indexed_vector & work_vec, +bool sparse_matrix::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned i0, indexed_vector & work_vec, lp_settings & settings) { remove_zero_elements_and_set_data_on_existing_elements_not_adjusted(i0, work_vec, settings); // all non-zero elements in m_work_pivot_vector are new @@ -557,11 +557,11 @@ void sparse_matrix::double_solve_U_y(indexed_vector& y, const lp_settin active_rows.clear(); solve_U_y_indexed_only(y_orig, settings, active_rows); add_delta_to_solution(y_orig, y); - y.clp_up(); + y.clean_up(); } else { // the dense version solve_U_y(y_orig.m_data); add_delta_to_solution(y_orig.m_data, y.m_data); - y.restore_index_and_clp_from_data(); + y.restore_index_and_clean_from_data(); } lp_assert(y.is_OK()); } diff --git a/src/util/lp/sparse_matrix_instances.cpp b/src/util/lp/sparse_matrix_instances.cpp index cf859a6a2..80a9b8ef5 100644 --- a/src/util/lp/sparse_matrix_instances.cpp +++ b/src/util/lp/sparse_matrix_instances.cpp @@ -24,7 +24,7 @@ template void sparse_matrix::remove_element(vector::replace_column(unsigned int, indexed_vector&, lp_settings&); template void sparse_matrix::set(unsigned int, unsigned int, double); template void sparse_matrix::set_max_in_row(vector >&); -template bool sparse_matrix::set_row_from_work_vector_and_clp_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); +template bool sparse_matrix::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); template bool sparse_matrix::shorten_active_matrix(unsigned int, eta_matrix*); template void sparse_matrix::solve_y_U(vector&) const; template sparse_matrix::sparse_matrix(static_matrix const&, vector&); @@ -41,7 +41,7 @@ template void sparse_matrix::prepare_for_factorization(); template void sparse_matrix::remove_element(vector> &, indexed_value&); template void sparse_matrix::replace_column(unsigned int, indexed_vector&, lp_settings&); template void sparse_matrix::set_max_in_row(vector>&); -template bool sparse_matrix::set_row_from_work_vector_and_clp_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); +template bool sparse_matrix::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); template bool sparse_matrix::shorten_active_matrix(unsigned int, eta_matrix*); template void sparse_matrix::solve_y_U(vector&) const; template sparse_matrix::sparse_matrix(static_matrix const&, vector&); @@ -57,7 +57,7 @@ template void sparse_matrix>::prepare_for_factorizati template void sparse_matrix>::remove_element(vector>&, indexed_value&); template void sparse_matrix>::replace_column(unsigned int, indexed_vector&, lp_settings&); template void sparse_matrix>::set_max_in_row(vector>&); -template bool sparse_matrix>::set_row_from_work_vector_and_clp_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); +template bool sparse_matrix>::set_row_from_work_vector_and_clean_work_vector_not_adjusted(unsigned int, indexed_vector&, lp_settings&); template bool sparse_matrix>::shorten_active_matrix(unsigned int, eta_matrix >*); template void sparse_matrix>::solve_y_U(vector&) const; template sparse_matrix>::sparse_matrix(static_matrix > const&, vector&); diff --git a/src/util/lp/square_dense_submatrix.h b/src/util/lp/square_dense_submatrix.h index 5ffed7818..c5aa1fa97 100644 --- a/src/util/lp/square_dense_submatrix.h +++ b/src/util/lp/square_dense_submatrix.h @@ -187,7 +187,7 @@ public: } } } - m_work_vector.clp_up(); + m_work_vector.clean_up(); lp_assert(m_work_vector.is_OK()); w = m_work_vector; #endif diff --git a/src/util/lp/static_matrix.h b/src/util/lp/static_matrix.h index f1d7f064b..74bcf17cf 100644 --- a/src/util/lp/static_matrix.h +++ b/src/util/lp/static_matrix.h @@ -193,7 +193,7 @@ public: void scan_row_to_work_vector(unsigned i); - void clp_row_work_vector(unsigned i); + void clean_row_work_vector(unsigned i); #ifdef LEAN_DEBUG diff --git a/src/util/lp/static_matrix.hpp b/src/util/lp/static_matrix.hpp index a3f69c9bf..1a88b567d 100644 --- a/src/util/lp/static_matrix.hpp +++ b/src/util/lp/static_matrix.hpp @@ -61,7 +61,7 @@ template bool static_matrix::pivot_row_to_row_giv } } - // clp the work vector + // clean the work vector for (unsigned k = 0; k < prev_size_ii; k++) { m_vector_of_row_offsets[ii_row_vals[k].m_j] = -1; } From 9dc7ba73eb13a42f24ca77471290a22aaf26dc94 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 10 Jul 2017 11:57:33 -0700 Subject: [PATCH 135/159] use a faster version of get_model in debug checks Signed-off-by: Lev Nachmanson --- src/util/lp/lar_solver.cpp | 10 +++++++++- src/util/lp/lar_solver.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index 93cd6a118..0f9fa938a 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -897,7 +897,7 @@ bool lar_solver::all_constraints_hold() const { if (m_settings.get_cancel_flag()) return true; std::unordered_map var_map; - get_model(var_map); + get_model_do_not_care_about_diff_vars(var_map); for (unsigned i = 0; i < m_constraints.size(); i++) { if (!constraint_holds(*m_constraints[i], var_map)) { @@ -1137,6 +1137,14 @@ void lar_solver::get_model(std::unordered_map & variable_values) } while (i != m_mpq_lar_core_solver.m_r_x.size()); } +void lar_solver::get_model_do_not_care_about_diff_vars(std::unordered_map & variable_values) const { + for (unsigned i = 0; i < m_mpq_lar_core_solver.m_r_x.size(); i++ ) { + const impq & rp = m_mpq_lar_core_solver.m_r_x[i]; + variable_values[i] = rp.x + rp.y; + } +} + + std::string lar_solver::get_variable_name(var_index vi) const { return get_column_name(vi); } diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index 1a12a5953..e155d31a1 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -372,6 +372,7 @@ public: void get_model(std::unordered_map & variable_values) const; + void get_model_do_not_care_about_diff_vars(std::unordered_map & variable_values) const; std::string get_variable_name(var_index vi) const; From 581098299be0c3f8893d24f4260d9dc44b88dac4 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 10 Jul 2017 12:04:58 -0700 Subject: [PATCH 136/159] change the order of initializations in the constructor of imp in theory_lra Signed-off-by: Lev Nachmanson --- src/smt/theory_lra.cpp | 4 ++-- src/util/lp/lar_solver.cpp | 2 +- src/util/lp/lar_solver.h | 2 +- src/util/lp/nra_solver.cpp | 2 +- src/util/lp/nra_solver.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 72654de18..c6fe07c4d 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -721,10 +721,10 @@ namespace smt { m_asserted_qhead(0), m_assume_eq_head(0), m_num_conflicts(0), + m_use_nra_model(false), m_model_eqs(DEFAULT_HASHTABLE_INITIAL_CAPACITY, var_value_hash(*this), var_value_eq(*this)), m_solver(0), - m_resource_limit(*this), - m_use_nra_model(false) { + m_resource_limit(*this) { } ~imp() { diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index 0f9fa938a..0b5508ec9 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -1,7 +1,7 @@ #include "util/lp/lar_solver.h" /* Copyright (c) 2017 Microsoft Corporation - Author: Lev Nachmanson + Author: Nikolaj Bjorner, Lev Nachmanson */ namespace lp { diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index e155d31a1..e1b6973e8 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -1,6 +1,6 @@ /* Copyright (c) 2017 Microsoft Corporation - Author: Lev Nachmanson + Author: Nikolaj Bjorner, Lev Nachmanson */ #pragma once #include "util/vector.h" diff --git a/src/util/lp/nra_solver.cpp b/src/util/lp/nra_solver.cpp index efa003b37..327d2b70f 100644 --- a/src/util/lp/nra_solver.cpp +++ b/src/util/lp/nra_solver.cpp @@ -1,6 +1,6 @@ /* Copyright (c) 2017 Microsoft Corporation - Author: Lev Nachmanson + Author: Nikolaj Bjorner */ #include "util/lp/lar_solver.h" diff --git a/src/util/lp/nra_solver.h b/src/util/lp/nra_solver.h index 68c9e98e5..70e614e91 100644 --- a/src/util/lp/nra_solver.h +++ b/src/util/lp/nra_solver.h @@ -1,6 +1,6 @@ /* Copyright (c) 2017 Microsoft Corporation - Author: Lev Nachmanson + Author: Nikolaj Bjorner */ #pragma once From 2fe846d9fcadff7242991d7ab3e27b1aa80dc069 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 10 Jul 2017 16:34:23 -0700 Subject: [PATCH 137/159] fix a bug in the lar_solver::m_status update during push/pop Signed-off-by: Lev Nachmanson --- src/shell/lp_frontend.cpp | 2 +- src/smt/theory_lra.cpp | 1 + src/test/lp/lp.cpp | 24 +++--- src/util/lp/int_solver.cpp | 17 +++-- src/util/lp/lar_core_solver.hpp | 12 +-- src/util/lp/lar_solver.cpp | 66 +++++++++-------- src/util/lp/lar_solver.h | 13 +++- src/util/lp/lp_core_solver_base.h | 12 ++- src/util/lp/lp_core_solver_base.hpp | 13 ++-- src/util/lp/lp_dual_core_solver.hpp | 30 ++++---- src/util/lp/lp_dual_simplex.hpp | 44 +++++------ src/util/lp/lp_primal_core_solver.h | 10 +-- src/util/lp/lp_primal_core_solver.hpp | 74 +++++++++---------- src/util/lp/lp_primal_core_solver_tableau.hpp | 38 +++++----- src/util/lp/lp_primal_simplex.hpp | 2 +- src/util/lp/lp_settings.h | 2 +- src/util/lp/lp_settings.hpp | 24 +++--- src/util/lp/lp_solver.hpp | 12 +-- src/util/lp/quick_xplain.cpp | 6 +- 19 files changed, 212 insertions(+), 190 deletions(-) diff --git a/src/shell/lp_frontend.cpp b/src/shell/lp_frontend.cpp index 694205395..83f5e9e2e 100644 --- a/src/shell/lp_frontend.cpp +++ b/src/shell/lp_frontend.cpp @@ -84,7 +84,7 @@ void run_solver(lp_params & params, char const * mps_file_name) { solver->find_maximal_solution(); *(solver->settings().get_message_ostream()) << "status is " << lp_status_to_string(solver->get_status()) << std::endl; - if (solver->get_status() == lp::OPTIMAL) { + if (solver->get_status() == lp::lp_status::OPTIMAL) { if (params.min()) { solver->flip_costs(); } diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index c6fe07c4d..e2b4ea944 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -1165,6 +1165,7 @@ namespace smt { } final_check_status final_check_eh() { + TRACE("lar_solver", tout << "ddd=" <<++lp::lp_settings::ddd << std::endl;); m_use_nra_model = false; lbool is_sat = l_true; if (m_solver->get_status() != lp::lp_status::OPTIMAL) { diff --git a/src/test/lp/lp.cpp b/src/test/lp/lp.cpp index 173bc3b12..d402d4ff7 100644 --- a/src/test/lp/lp.cpp +++ b/src/test/lp/lp.cpp @@ -1656,7 +1656,7 @@ void solve_some_mps(argument_parser & args_parser) { } if (!solve_for_rational) { solve_mps(file_names[6], false, 0, time_limit, false, dual, compare_with_primal, args_parser); - solve_mps_with_known_solution(file_names[3], nullptr, INFEASIBLE, dual); // chvatal: 135(d) + solve_mps_with_known_solution(file_names[3], nullptr, lp_status::INFEASIBLE, dual); // chvatal: 135(d) std::unordered_map sol; sol["X1"] = 0; sol["X2"] = 6; @@ -1666,8 +1666,8 @@ void solve_some_mps(argument_parser & args_parser) { sol["X6"] = 1; sol["X7"] = 1; sol["X8"] = 0; - solve_mps_with_known_solution(file_names[9], &sol, OPTIMAL, dual); - solve_mps_with_known_solution(file_names[0], &sol, OPTIMAL, dual); + solve_mps_with_known_solution(file_names[9], &sol, lp_status::OPTIMAL, dual); + solve_mps_with_known_solution(file_names[0], &sol, lp_status::OPTIMAL, dual); sol.clear(); sol["X1"] = 25.0/14.0; // sol["X2"] = 0; @@ -1676,10 +1676,10 @@ void solve_some_mps(argument_parser & args_parser) { // sol["X5"] = 0; // sol["X6"] = 0; // sol["X7"] = 9.0/14.0; - solve_mps_with_known_solution(file_names[5], &sol, OPTIMAL, dual); // chvatal: 135(e) - solve_mps_with_known_solution(file_names[4], &sol, OPTIMAL, dual); // chvatal: 135(e) - solve_mps_with_known_solution(file_names[2], nullptr, UNBOUNDED, dual); // chvatal: 135(c) - solve_mps_with_known_solution(file_names[1], nullptr, UNBOUNDED, dual); // chvatal: 135(b) + solve_mps_with_known_solution(file_names[5], &sol, lp_status::OPTIMAL, dual); // chvatal: 135(e) + solve_mps_with_known_solution(file_names[4], &sol, lp_status::OPTIMAL, dual); // chvatal: 135(e) + solve_mps_with_known_solution(file_names[2], nullptr, lp_status::UNBOUNDED, dual); // chvatal: 135(c) + solve_mps_with_known_solution(file_names[1], nullptr, lp_status::UNBOUNDED, dual); // chvatal: 135(b) solve_mps(file_names[8], false, 0, time_limit, false, dual, compare_with_primal, args_parser); // return; for (auto& s : file_names) { @@ -1745,7 +1745,7 @@ void solve_rational() { expected_sol["x7"] = lp::mpq(1); expected_sol["x8"] = lp::mpq(0); solver.find_maximal_solution(); - lp_assert(solver.get_status() == OPTIMAL); + lp_assert(solver.get_status() == lp_status::OPTIMAL); for (auto it : expected_sol) { lp_assert(it.second == solver.get_column_value_by_name(it.first)); } @@ -2433,12 +2433,12 @@ void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_read sw.start(); lp_status status = solver->solve(); std::cout << "status is " << lp_status_to_string(status) << ", processed for " << sw.get_current_seconds() <<" seconds, and " << solver->get_total_iterations() << " iterations" << std::endl; - if (solver->get_status() == INFEASIBLE) { + if (solver->get_status() == lp_status::INFEASIBLE) { vector> evidence; solver->get_infeasibility_explanation(evidence); } if (args_parser.option_is_used("--randomize_lar")) { - if (solver->get_status() != OPTIMAL) { + if (solver->get_status() != lp_status::OPTIMAL) { std::cout << "cannot check randomize on an infeazible problem" << std::endl; return; } @@ -2717,7 +2717,7 @@ void test_term() { auto status = solver.solve(); std::cout << lp_status_to_string(status) << std::endl; std::unordered_map model; - if (status != OPTIMAL) + if (status != lp_status::OPTIMAL) return; solver.get_model(model); @@ -2745,7 +2745,7 @@ void test_evidence_for_total_inf_simple(argument_parser & args_parser) { auto status = solver.solve(); std::cout << lp_status_to_string(status) << std::endl; std::unordered_map model; - lp_assert(solver.get_status() == INFEASIBLE); + lp_assert(solver.get_status() == lp_status::INFEASIBLE); } void test_bound_propagation_one_small_sample1() { /* diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index f416ad98c..46d46e981 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -19,7 +19,7 @@ void int_solver::fix_non_base_columns() { } if (!change) return; - if (m_lar_solver->find_feasible_solution() == INFEASIBLE) + if (m_lar_solver->find_feasible_solution() == lp_status::INFEASIBLE) failed(); init_inf_int_set(); lp_assert(is_feasible() && inf_int_set_is_correct()); @@ -109,14 +109,13 @@ int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { } bool int_solver::mk_gomory_cut(unsigned row_index, explanation & ex) { - lp_assert(false); - return true; + + auto row_it = m_lar_solver->get_iterator_on_row(row_index); + + unsigned x_i = m_lar_solver->get_base_column_in_row(row_index); + + lp_assert(column_is_int_inf(x_i)); /* - const auto & row = m_lar_solver->A_r().m_rows[row_index]; - // The following assertion is wrong. It may be violated in mixed-integer problems. - // SASSERT(!all_coeff_int(r)); - theory_var x_i = r.get_base_var(); - SASSERT(is_int(x_i)); // The following assertion is wrong. It may be violated in mixed-real-interger problems. // The check is_gomory_cut_target will discard rows where any variable contains infinitesimals. @@ -286,6 +285,8 @@ bool int_solver::mk_gomory_cut(unsigned row_index, explanation & ex) { ante.eqs().size(), ante.eqs().c_ptr(), ante, l))); return true; */ + delete row_it; + return true; } diff --git a/src/util/lp/lar_core_solver.hpp b/src/util/lp/lar_core_solver.hpp index 227d2910f..6f7f7e720 100644 --- a/src/util/lp/lar_core_solver.hpp +++ b/src/util/lp/lar_core_solver.hpp @@ -230,7 +230,7 @@ void lar_core_solver::solve() { lp_assert(m_r_solver.non_basic_columns_are_set_correctly()); lp_assert(m_r_solver.inf_set_is_correct()); if (m_r_solver.current_x_is_feasible() && m_r_solver.m_look_for_feasible_solution_only) { - m_r_solver.set_status(OPTIMAL); + m_r_solver.set_status(lp_status::OPTIMAL); return; } ++settings().st().m_need_to_solve_inf; @@ -240,8 +240,8 @@ void lar_core_solver::solve() { prefix_d(); lar_solution_signature solution_signature; vector changes_of_basis = find_solution_signature_with_doubles(solution_signature); - if (m_d_solver.get_status() == TIME_EXHAUSTED) { - m_r_solver.set_status(TIME_EXHAUSTED); + if (m_d_solver.get_status() == lp_status::TIME_EXHAUSTED) { + m_r_solver.set_status(lp_status::TIME_EXHAUSTED); return; } if (settings().use_tableau()) @@ -262,10 +262,10 @@ void lar_core_solver::solve() { m_r_solver.solve(); lp_assert(!settings().use_tableau() || r_basis_is_OK()); } - if (m_r_solver.get_status() == INFEASIBLE) { + if (m_r_solver.get_status() == lp_status::INFEASIBLE) { fill_not_improvable_zero_sum(); - } else if (m_r_solver.get_status() != UNBOUNDED) { - m_r_solver.set_status(OPTIMAL); + } else if (m_r_solver.get_status() != lp_status::UNBOUNDED) { + m_r_solver.set_status(lp_status::OPTIMAL); } lp_assert(r_basis_is_OK()); lp_assert(m_r_solver.non_basic_columns_are_set_correctly()); diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index 0b5508ec9..8dcd5a327 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -27,7 +27,7 @@ void clear() {lp_assert(false); // not implemented } -lar_solver::lar_solver() : m_status(OPTIMAL), +lar_solver::lar_solver() : m_status(lp_status::OPTIMAL), m_infeasible_column_index(-1), m_terms_start_index(1000000), m_mpq_lar_core_solver(m_settings, *this) @@ -293,11 +293,11 @@ lp_status lar_solver::find_feasible_solution() { } lp_status lar_solver::solve() { - if (m_status == INFEASIBLE) { + if (m_status == lp_status::INFEASIBLE) { return m_status; } solve_with_core_solver(); - if (m_status != INFEASIBLE) { + if (m_status != lp_status::INFEASIBLE) { if (m_settings.bound_propagation()) detect_rows_with_changed_bounds(); } @@ -325,7 +325,6 @@ vector lar_solver::get_list_of_all_var_indices() const { void lar_solver::push() { m_simplex_strategy = m_settings.simplex_strategy(); m_simplex_strategy.push(); - m_status.push(); m_vars_to_ul_pairs.push(); m_infeasible_column_index.push(); m_mpq_lar_core_solver.push(); @@ -335,7 +334,7 @@ void lar_solver::push() { m_constraint_count.push(); } -void lar_solver::clean_large_elements_after_pop(unsigned n, int_set& set) { +void lar_solver::clean_popped_elements(unsigned n, int_set& set) { vector to_remove; for (unsigned j: set.m_index) if (j >= n) @@ -345,14 +344,15 @@ void lar_solver::clean_large_elements_after_pop(unsigned n, int_set& set) { } void lar_solver::shrink_inf_set_after_pop(unsigned n, int_set & set) { - clean_large_elements_after_pop(n, set); + clean_popped_elements(n, set); set.resize(n); } void lar_solver::pop(unsigned k) { + TRACE("lar_solver", tout << "k = " << k << std::endl;); + int n_was = static_cast(m_ext_vars_to_columns.size()); - m_status.pop(k); m_infeasible_column_index.pop(k); unsigned n = m_vars_to_ul_pairs.peek_size(k); for (unsigned j = n_was; j-- > n;) @@ -364,10 +364,11 @@ void lar_solver::pop(unsigned k) { m_vars_to_ul_pairs.pop(k); m_mpq_lar_core_solver.pop(k); - clean_large_elements_after_pop(n, m_columns_with_changed_bound); + clean_popped_elements(n, m_columns_with_changed_bound); unsigned m = A_r().row_count(); - clean_large_elements_after_pop(m, m_rows_with_changed_bounds); + clean_popped_elements(m, m_rows_with_changed_bounds); clean_inf_set_of_r_solver_after_pop(); + m_status = m_mpq_lar_core_solver.m_r_solver.current_x_is_feasible()? lp_status::OPTIMAL: lp_status::UNKNOWN; lp_assert(m_settings.simplex_strategy() == simplex_strategy_enum::undecided || (!use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); @@ -404,7 +405,7 @@ bool lar_solver::maximize_term_on_tableau(const vector decide_on_strategy_and_adjust_initial_state(); m_mpq_lar_core_solver.solve(); - if (m_mpq_lar_core_solver.m_r_solver.get_status() == UNBOUNDED) + if (m_mpq_lar_core_solver.m_r_solver.get_status() == lp_status::UNBOUNDED) return false; term_max = 0; @@ -482,7 +483,7 @@ bool lar_solver::maximize_term_on_corrected_r_solver(const vector & variable_values) const { mpq delta = mpq(1, 2); // start from 0.5 to have less clashes - lp_assert(m_status == OPTIMAL); + lp_assert(m_status == lp_status::OPTIMAL); unsigned i; do { @@ -1353,7 +1354,7 @@ void lar_solver::pop_tableau() { void lar_solver::clean_inf_set_of_r_solver_after_pop() { vector became_feas; - clean_large_elements_after_pop(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.m_inf_set); + clean_popped_elements(A_r().column_count(), m_mpq_lar_core_solver.m_r_solver.m_inf_set); std::unordered_set basic_columns_with_changed_cost; auto inf_index_copy = m_mpq_lar_core_solver.m_r_solver.m_inf_set.m_index; for (auto j: inf_index_copy) { @@ -1598,6 +1599,7 @@ bool lar_solver::bound_is_integer_if_needed(unsigned j, const mpq & right_side) } constraint_index lar_solver::add_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side) { + TRACE("lar_solver", tout << "j = " << j << std::endl;); constraint_index ci = m_constraints.size(); if (!is_term(j)) { // j is a var lp_assert(bound_is_integer_if_needed(j, right_side)); @@ -1816,7 +1818,7 @@ void lar_solver::update_upper_bound_column_type_and_bound(var_index j, lconstrai set_low_bound_witness(j, ci); m_columns_with_changed_bound.insert(j); if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; } else { @@ -1828,7 +1830,7 @@ void lar_solver::update_upper_bound_column_type_and_bound(var_index j, lconstrai { auto v = numeric_pair(right_side, zero_of_type()); if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; set_low_bound_witness(j, ci); m_infeasible_column_index = j; } @@ -1850,7 +1852,7 @@ void lar_solver::update_upper_bound_column_type_and_bound(var_index j, lconstrai } void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lp_assert(m_status == 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_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j])); mpq y_of_bound(0); switch (kind) { case LT: @@ -1865,7 +1867,7 @@ void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kin } if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; lp_assert(false); m_infeasible_column_index = j; } @@ -1886,7 +1888,7 @@ void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kin set_low_bound_witness(j, ci); } if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; } else if (low == m_mpq_lar_core_solver.m_r_upper_bounds[j]) { @@ -1898,12 +1900,12 @@ void lar_solver::update_boxed_column_type_and_bound(var_index j, lconstraint_kin { auto v = numeric_pair(right_side, zero_of_type()); if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; set_upper_bound_witness(j, ci); } else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; set_low_bound_witness(j, ci); } @@ -1937,7 +1939,7 @@ void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint m_columns_with_changed_bound.insert(j); if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; } else { @@ -1961,7 +1963,7 @@ void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint { auto v = numeric_pair(right_side, zero_of_type()); if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; set_upper_bound_witness(j, ci); } @@ -1982,15 +1984,15 @@ void lar_solver::update_low_bound_column_type_and_bound(var_index j, lconstraint } void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) { - lp_assert(m_status == 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 == INFEASIBLE || (m_mpq_lar_core_solver.m_r_low_bounds()[j].y.is_zero() && m_mpq_lar_core_solver.m_r_upper_bounds()[j].y.is_zero())); + lp_assert(m_status == lp_status::INFEASIBLE || (m_mpq_lar_core_solver.m_column_types()[j] == column_type::fixed && m_mpq_lar_core_solver.m_r_low_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j])); + lp_assert(m_status == lp_status::INFEASIBLE || (m_mpq_lar_core_solver.m_r_low_bounds()[j].y.is_zero() && m_mpq_lar_core_solver.m_r_upper_bounds()[j].y.is_zero())); auto v = numeric_pair(right_side, mpq(0)); mpq y_of_bound(0); switch (kind) { case LT: if (v <= m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; set_upper_bound_witness(j, ci); } @@ -1998,7 +2000,7 @@ void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kin case LE: { if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; set_upper_bound_witness(j, ci); } @@ -2007,7 +2009,7 @@ void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kin case GT: { if (v >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; set_low_bound_witness(j, ci); } @@ -2016,7 +2018,7 @@ void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kin case GE: { if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; set_low_bound_witness(j, ci); } @@ -2025,12 +2027,12 @@ void lar_solver::update_fixed_column_type_and_bound(var_index j, lconstraint_kin case EQ: { if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; set_upper_bound_witness(j, ci); } else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) { - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; m_infeasible_column_index = j; set_low_bound_witness(j, ci); } diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index e1b6973e8..2249beaa1 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -48,7 +48,7 @@ class lar_solver : public column_namer { }; //////////////////// fields ////////////////////////// lp_settings m_settings; - stacked_value m_status; + lp_status m_status; stacked_value m_simplex_strategy; std::unordered_map m_ext_vars_to_columns; vector m_columns_to_ext_vars_or_term_indices; @@ -222,7 +222,7 @@ public: vector get_list_of_all_var_indices() const; void push(); - static void clean_large_elements_after_pop(unsigned n, int_set& set); + static void clean_popped_elements(unsigned n, int_set& set); static void shrink_inf_set_after_pop(unsigned n, int_set & set); @@ -447,5 +447,14 @@ public: } bool bound_is_integer_if_needed(unsigned j, const mpq & right_side) const; + linear_combination_iterator * get_iterator_on_row(unsigned i) { + return m_mpq_lar_core_solver.m_r_solver.get_iterator_on_row(i); + } + + unsigned get_base_column_in_row(unsigned row_index) const { + return m_mpq_lar_core_solver.m_r_solver.get_base_column_in_row(row_index); + } + + }; } diff --git a/src/util/lp/lp_core_solver_base.h b/src/util/lp/lp_core_solver_base.h index 28cb14011..12c93ec93 100644 --- a/src/util/lp/lp_core_solver_base.h +++ b/src/util/lp/lp_core_solver_base.h @@ -26,7 +26,14 @@ class lp_core_solver_base { private: lp_status m_status; public: - bool current_x_is_feasible() const { return m_inf_set.size() == 0; } + bool current_x_is_feasible() const { + TRACE("feas", + if (m_inf_set.size()) { + tout << "column " << m_inf_set.m_index[0] << " is infeasible" << std::endl; + } + ); + return m_inf_set.size() == 0; + } bool current_x_is_infeasible() const { return m_inf_set.size() != 0; } int_set m_inf_set; bool m_using_infeas_costs; @@ -700,5 +707,8 @@ public: } void calculate_pivot_row(unsigned i); + unsigned get_base_column_in_row(unsigned row_index) const { + return m_basis[row_index]; + } }; } diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp index 26d6f49c7..bd3410b45 100644 --- a/src/util/lp/lp_core_solver_base.hpp +++ b/src/util/lp/lp_core_solver_base.hpp @@ -24,7 +24,7 @@ lp_core_solver_base(static_matrix & A, const vector & upper_bound_values): m_total_iterations(0), m_iters_with_no_cost_growing(0), - m_status(FEASIBLE), + m_status(lp_status::FEASIBLE), m_inf_set(A.column_count()), m_using_infeas_costs(false), m_pivot_row_of_B_1(A.row_count()), @@ -534,7 +534,7 @@ update_basis_and_x(int entering, int leaving, X const & tt) { if (!find_x_by_solving()) { restore_x(entering, tt); if(A_mult_x_is_off()) { - m_status = FLOATING_POINT_ERROR; + m_status = lp_status::FLOATING_POINT_ERROR; m_iters_with_no_cost_growing++; return false; } @@ -544,7 +544,7 @@ update_basis_and_x(int entering, int leaving, X const & tt) { if (m_factorization->get_status() != LU_status::OK) { std::stringstream s; // s << "failing refactor on off_result for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << total_iterations(); - m_status = FLOATING_POINT_ERROR; + m_status = lp_status::FLOATING_POINT_ERROR; return false; } return false; @@ -566,19 +566,19 @@ update_basis_and_x(int entering, int leaving, X const & tt) { init_lu(); if (m_factorization->get_status() != LU_status::OK) { if (m_look_for_feasible_solution_only && !precise()) { - m_status = UNSTABLE; + m_status = lp_status::UNSTABLE; delete m_factorization; m_factorization = nullptr; return false; } // LP_OUT(m_settings, "failing refactor for entering = " << entering << ", leaving = " << leaving << " total_iterations = " << total_iterations() << std::endl); restore_x_and_refactor(entering, leaving, tt); - if (m_status == FLOATING_POINT_ERROR) + if (m_status == lp_status::FLOATING_POINT_ERROR) return false; lp_assert(!A_mult_x_is_off()); m_iters_with_no_cost_growing++; // LP_OUT(m_settings, "rolled back after failing of init_factorization()" << std::endl); - m_status = UNSTABLE; + m_status = lp_status::UNSTABLE; return false; } return true; @@ -960,7 +960,6 @@ template void lp_core_solver_base::pivot_fixed_v unsigned basic_j = m_basis[i]; if (get_column_type(basic_j) != column_type::fixed) continue; - //todo run over the row here!!!!! call get_iterator_on_row(); T a; unsigned j; auto * it = get_iterator_on_row(i); diff --git a/src/util/lp/lp_dual_core_solver.hpp b/src/util/lp/lp_dual_core_solver.hpp index 5038fc4ea..1b6e696d7 100644 --- a/src/util/lp/lp_dual_core_solver.hpp +++ b/src/util/lp/lp_dual_core_solver.hpp @@ -82,11 +82,11 @@ template void lp_dual_core_solver::start_with_ini } template bool lp_dual_core_solver::done() { - if (this->get_status() == OPTIMAL) { + if (this->get_status() == lp_status::OPTIMAL) { return true; } if (this->total_iterations() > this->m_settings.max_total_number_of_iterations) { // debug !!!! - this->set_status(ITERATIONS_EXHAUSTED); + this->set_status(lp_status::ITERATIONS_EXHAUSTED); return true; } return false; // todo, need to be more cases @@ -170,8 +170,8 @@ template void lp_dual_core_solver::pricing_loop(u } } while (i != initial_offset_in_rows && rows_left); if (m_r == -1) { - if (this->get_status() != UNSTABLE) { - this->set_status(OPTIMAL); + if (this->get_status() != lp_status::UNSTABLE) { + this->set_status(lp_status::OPTIMAL); } } else { m_p = this->m_basis[m_r]; @@ -181,10 +181,10 @@ template void lp_dual_core_solver::pricing_loop(u return; } // failure in advance_on_known_p - if (this->get_status() == FLOATING_POINT_ERROR) { + if (this->get_status() == lp_status::FLOATING_POINT_ERROR) { return; } - this->set_status(UNSTABLE); + this->set_status(lp_status::UNSTABLE); m_forbidden_rows.insert(m_r); } } @@ -466,12 +466,12 @@ template void lp_dual_core_solver::revert_to_prev this->change_basis_unconditionally(m_p, m_q); init_factorization(this->m_factorization, this->m_A, this->m_basis, this->m_settings); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); // complete failure + this->set_status(lp_status::FLOATING_POINT_ERROR); // complete failure return; } recover_leaving(); if (!this->find_x_by_solving()) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); return; } recalculate_xB_and_d(); @@ -551,10 +551,10 @@ template bool lp_dual_core_solver::delta_keeps_th } template void lp_dual_core_solver::set_status_to_tentative_dual_unbounded_or_dual_unbounded() { - if (this->get_status() == TENTATIVE_DUAL_UNBOUNDED) { - this->set_status(DUAL_UNBOUNDED); + if (this->get_status() == lp_status::TENTATIVE_DUAL_UNBOUNDED) { + this->set_status(lp_status::DUAL_UNBOUNDED); } else { - this->set_status(TENTATIVE_DUAL_UNBOUNDED); + this->set_status(lp_status::TENTATIVE_DUAL_UNBOUNDED); } } @@ -660,7 +660,7 @@ template bool lp_dual_core_solver::ratio_test() { set_status_to_tentative_dual_unbounded_or_dual_unbounded(); return false; } - this->set_status(FEASIBLE); + this->set_status(lp_status::FEASIBLE); find_q_and_tight_set(); if (!tight_breakpoinst_are_all_boxed()) break; T del = m_delta - delta_lost_on_flips_of_tight_breakpoints() * initial_delta_sign; @@ -716,10 +716,10 @@ template void lp_dual_core_solver::update_xb_afte template void lp_dual_core_solver::one_iteration() { unsigned number_of_rows_to_try = get_number_of_rows_to_try_for_leaving(); unsigned offset_in_rows = this->m_settings.random_next() % this->m_m(); - if (this->get_status() == TENTATIVE_DUAL_UNBOUNDED) { + if (this->get_status() == lp_status::TENTATIVE_DUAL_UNBOUNDED) { number_of_rows_to_try = this->m_m(); } else { - this->set_status(FEASIBLE); + this->set_status(lp_status::FEASIBLE); } pricing_loop(number_of_rows_to_try, offset_in_rows); lp_assert(problem_is_dual_feasible()); @@ -736,7 +736,7 @@ template void lp_dual_core_solver::solve() { // s return; } one_iteration(); - } while (this->get_status() != FLOATING_POINT_ERROR && this->get_status() != DUAL_UNBOUNDED && this->get_status() != OPTIMAL && + } while (this->get_status() != lp_status::FLOATING_POINT_ERROR && this->get_status() != lp_status::DUAL_UNBOUNDED && this->get_status() != lp_status::OPTIMAL && this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements && this->total_iterations() <= this->m_settings.max_total_number_of_iterations); } diff --git a/src/util/lp/lp_dual_simplex.hpp b/src/util/lp/lp_dual_simplex.hpp index 5a585c68e..7f6f686ca 100644 --- a/src/util/lp/lp_dual_simplex.hpp +++ b/src/util/lp/lp_dual_simplex.hpp @@ -7,23 +7,23 @@ namespace lp{ template void lp_dual_simplex::decide_on_status_after_stage1() { switch (m_core_solver->get_status()) { - case OPTIMAL: + case lp_status::OPTIMAL: if (this->m_settings.abs_val_is_smaller_than_artificial_tolerance(m_core_solver->get_cost())) { - this->m_status = FEASIBLE; + this->m_status = lp_status::FEASIBLE; } else { - this->m_status = UNBOUNDED; + this->m_status = lp_status::UNBOUNDED; } break; - case DUAL_UNBOUNDED: + case lp_status::DUAL_UNBOUNDED: lp_unreachable(); - case ITERATIONS_EXHAUSTED: - this->m_status = ITERATIONS_EXHAUSTED; + case lp_status::ITERATIONS_EXHAUSTED: + this->m_status = lp_status::ITERATIONS_EXHAUSTED; break; - case TIME_EXHAUSTED: - this->m_status = TIME_EXHAUSTED; + case lp_status::TIME_EXHAUSTED: + this->m_status = lp_status::TIME_EXHAUSTED; break; - case FLOATING_POINT_ERROR: - this->m_status = FLOATING_POINT_ERROR; + case lp_status::FLOATING_POINT_ERROR: + this->m_status = lp_status::FLOATING_POINT_ERROR; break; default: lp_unreachable(); @@ -99,20 +99,20 @@ template void lp_dual_simplex::solve_for_stage2() m_core_solver->solve_yB(m_core_solver->m_y); m_core_solver->fill_reduced_costs_from_m_y_by_rows(); m_core_solver->start_with_initial_basis_and_make_it_dual_feasible(); - m_core_solver->set_status(FEASIBLE); + m_core_solver->set_status(lp_status::FEASIBLE); m_core_solver->solve(); switch (m_core_solver->get_status()) { - case OPTIMAL: - this->m_status = OPTIMAL; + case lp_status::OPTIMAL: + this->m_status = lp_status::OPTIMAL; break; - case DUAL_UNBOUNDED: - this->m_status = INFEASIBLE; + case lp_status::DUAL_UNBOUNDED: + this->m_status = lp_status::INFEASIBLE; break; - case TIME_EXHAUSTED: - this->m_status = TIME_EXHAUSTED; + case lp_status::TIME_EXHAUSTED: + this->m_status = lp_status::TIME_EXHAUSTED; break; - case FLOATING_POINT_ERROR: - this->m_status = FLOATING_POINT_ERROR; + case lp_status::FLOATING_POINT_ERROR: + this->m_status = lp_status::FLOATING_POINT_ERROR; break; default: lp_unreachable(); @@ -151,7 +151,7 @@ template void lp_dual_simplex::stage1() { m_core_solver->start_with_initial_basis_and_make_it_dual_feasible(); if (this->m_settings.abs_val_is_smaller_than_artificial_tolerance(m_core_solver->get_cost())) { // skipping stage 1 - m_core_solver->set_status(OPTIMAL); + m_core_solver->set_status(lp_status::OPTIMAL); m_core_solver->set_total_iterations(0); } else { m_core_solver->solve(); @@ -336,7 +336,7 @@ template void lp_dual_simplex::find_maximal_solut this->flip_costs(); // do it for now, todo ( remove the flipping) this->cleanup(); - if (this->m_status == INFEASIBLE) { + if (this->m_status == lp_status::INFEASIBLE) { return; } this->fill_matrix_A_and_init_right_side(); @@ -346,7 +346,7 @@ template void lp_dual_simplex::find_maximal_solut fill_first_stage_solver_fields(); copy_m_b_aside_and_set_it_to_zeros(); stage1(); - if (this->m_status == FEASIBLE) { + if (this->m_status == lp_status::FEASIBLE) { stage2(); } } diff --git a/src/util/lp/lp_primal_core_solver.h b/src/util/lp/lp_primal_core_solver.h index 498288726..77784746a 100644 --- a/src/util/lp/lp_primal_core_solver.h +++ b/src/util/lp/lp_primal_core_solver.h @@ -469,7 +469,7 @@ public: X new_val_for_leaving; int leaving = find_leaving_tableau_rows(new_val_for_leaving); if (leaving == -1) { - this->set_status(OPTIMAL); + this->set_status(lp_status::OPTIMAL); return; } @@ -485,14 +485,14 @@ public: T a_ent; int entering = find_beneficial_column_in_row_tableau_rows(this->m_basis_heading[leaving], a_ent); if (entering == -1) { - this->set_status(INFEASIBLE); + this->set_status(lp_status::INFEASIBLE); return; } X theta = (this->m_x[leaving] - new_val_for_leaving) / a_ent; advance_on_entering_and_leaving_tableau_rows(entering, leaving, theta ); lp_assert(this->m_x[leaving] == new_val_for_leaving); if (this->current_x_is_feasible()) - this->set_status(OPTIMAL); + this->set_status(lp_status::OPTIMAL); } void fill_breakpoints_array(unsigned entering); @@ -508,7 +508,7 @@ public: void decide_on_status_when_cannot_find_entering() { lp_assert(!need_to_switch_costs()); - this->set_status(this->current_x_is_feasible()? OPTIMAL: INFEASIBLE); + this->set_status(this->current_x_is_feasible()? lp_status::OPTIMAL: lp_status::INFEASIBLE); } // void limit_theta_on_basis_column_for_feas_case_m_neg(unsigned j, const T & m, X & theta) { @@ -915,7 +915,7 @@ public: } else { m_converted_harris_eps = zero_of_type(); } - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } // constructor diff --git a/src/util/lp/lp_primal_core_solver.hpp b/src/util/lp/lp_primal_core_solver.hpp index d8d01f4b9..b3d6921d9 100644 --- a/src/util/lp/lp_primal_core_solver.hpp +++ b/src/util/lp/lp_primal_core_solver.hpp @@ -698,14 +698,14 @@ template void lp_primal_core_solver::advance_on_en int pivot_compare_result = this->pivots_in_column_and_row_are_different(entering, leaving); if (!pivot_compare_result){;} else if (pivot_compare_result == 2) { // the sign is changed, cannot continue - this->set_status(UNSTABLE); + this->set_status(lp_status::UNSTABLE); this->iters_with_no_cost_growing()++; return; } else { lp_assert(pivot_compare_result == 1); this->init_lu(); if (this->m_factorization == nullptr || this->m_factorization->get_status() != LU_status::OK) { - this->set_status(UNSTABLE); + this->set_status(lp_status::UNSTABLE); this->iters_with_no_cost_growing()++; return; } @@ -717,10 +717,10 @@ template void lp_primal_core_solver::advance_on_en t = -t; } if (!this->update_basis_and_x(entering, leaving, t)) { - if (this->get_status() == FLOATING_POINT_ERROR) + if (this->get_status() == lp_status::FLOATING_POINT_ERROR) return; if (this->m_look_for_feasible_solution_only) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); return; } init_reduced_costs(); @@ -733,7 +733,7 @@ template void lp_primal_core_solver::advance_on_en } if (this->current_x_is_feasible()) { - this->set_status(FEASIBLE); + this->set_status(lp_status::FEASIBLE); if (this->m_look_for_feasible_solution_only) return; } @@ -760,7 +760,7 @@ template void lp_primal_core_solver::advance_on_e X t; int leaving = find_leaving_and_t_precise(entering, t); if (leaving == -1) { - this->set_status(UNBOUNDED); + this->set_status(lp_status::UNBOUNDED); return; } advance_on_entering_and_leaving(entering, leaving, t); @@ -776,7 +776,7 @@ template void lp_primal_core_solver::advance_on_e int refresh_result = refresh_reduced_cost_at_entering_and_check_that_it_is_off(entering); if (refresh_result) { if (this->m_look_for_feasible_solution_only) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); return; } @@ -799,19 +799,19 @@ template void lp_primal_core_solver::advance_on_e // } - if (this->get_status() == UNSTABLE) { - this->set_status(FLOATING_POINT_ERROR); + if (this->get_status() == lp_status::UNSTABLE) { + this->set_status(lp_status::FLOATING_POINT_ERROR); return; } init_infeasibility_costs(); - this->set_status(UNSTABLE); + this->set_status(lp_status::UNSTABLE); return; } - if (this->get_status() == TENTATIVE_UNBOUNDED) { - this->set_status(UNBOUNDED); + if (this->get_status() == lp_status::TENTATIVE_UNBOUNDED) { + this->set_status(lp_status::UNBOUNDED); } else { - this->set_status(TENTATIVE_UNBOUNDED); + this->set_status(lp_status::TENTATIVE_UNBOUNDED); } return; } @@ -825,7 +825,7 @@ template void lp_primal_core_solver::push_forw template unsigned lp_primal_core_solver::get_number_of_non_basic_column_to_try_for_enter() { unsigned ret = static_cast(this->m_nbasis.size()); - if (this->get_status() == TENTATIVE_UNBOUNDED) + if (this->get_status() == lp_status::TENTATIVE_UNBOUNDED) return ret; // we really need to find entering with a large reduced cost if (ret > 300) { ret = (unsigned)(ret * this->m_settings.percent_of_entering_to_check / 100); @@ -852,12 +852,12 @@ template unsigned lp_primal_core_solver::solve() init_run(); if (this->current_x_is_feasible() && this->m_look_for_feasible_solution_only) { - this->set_status(FEASIBLE); + this->set_status(lp_status::FEASIBLE); return 0; } if ((!numeric_traits::precise()) && this->A_mult_x_is_off()) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); return 0; } do { @@ -867,8 +867,8 @@ template unsigned lp_primal_core_solver::solve() one_iteration(); lp_assert(!this->m_using_infeas_costs || this->costs_on_nbasis_are_zeros()); switch (this->get_status()) { - case OPTIMAL: // double check that we are at optimum - case INFEASIBLE: + case lp_status::OPTIMAL: // double check that we are at optimum + case lp_status::INFEASIBLE: if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible()) break; if (!numeric_traits::precise()) { @@ -877,7 +877,7 @@ template unsigned lp_primal_core_solver::solve() this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status (FLOATING_POINT_ERROR); + this->set_status (lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); @@ -885,7 +885,7 @@ template unsigned lp_primal_core_solver::solve() decide_on_status_when_cannot_find_entering(); break; } - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } else { // precise case if (this->m_look_for_feasible_solution_only) { // todo: keep the reduced costs correct all the time! init_reduced_costs(); @@ -893,31 +893,31 @@ template unsigned lp_primal_core_solver::solve() decide_on_status_when_cannot_find_entering(); break; } - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } } break; - case TENTATIVE_UNBOUNDED: + case lp_status::TENTATIVE_UNBOUNDED: this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); break; - case UNBOUNDED: + case lp_status::UNBOUNDED: if (this->current_x_is_infeasible()) { init_reduced_costs(); - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } break; - case UNSTABLE: + case lp_status::UNSTABLE: lp_assert(! (numeric_traits::precise())); this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); @@ -926,13 +926,13 @@ template unsigned lp_primal_core_solver::solve() default: break; // do nothing } - } while (this->get_status() != FLOATING_POINT_ERROR + } while (this->get_status() != lp_status::FLOATING_POINT_ERROR && - this->get_status() != UNBOUNDED + this->get_status() != lp_status::UNBOUNDED && - this->get_status() != OPTIMAL + this->get_status() != lp_status::OPTIMAL && - this->get_status() != INFEASIBLE + this->get_status() != lp_status::INFEASIBLE && this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements && @@ -940,7 +940,7 @@ template unsigned lp_primal_core_solver::solve() && !(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only)); - lp_assert(this->get_status() == FLOATING_POINT_ERROR + lp_assert(this->get_status() == lp_status::FLOATING_POINT_ERROR || this->current_x_is_feasible() == false || @@ -1028,7 +1028,7 @@ template T lp_primal_core_solver::calculate_no template void lp_primal_core_solver::find_feasible_solution() { this->m_look_for_feasible_solution_only = true; lp_assert(this->non_basic_columns_are_set_correctly()); - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); solve(); } @@ -1072,15 +1072,15 @@ template void lp_primal_core_solver::fill_breakpo template bool lp_primal_core_solver::done() { - if (this->get_status() == OPTIMAL || this->get_status() == FLOATING_POINT_ERROR) return true; - if (this->get_status() == INFEASIBLE) { + if (this->get_status() == lp_status::OPTIMAL || this->get_status() == lp_status::FLOATING_POINT_ERROR) return true; + if (this->get_status() == lp_status::INFEASIBLE) { return true; } if (this->m_iters_with_no_cost_growing >= this->m_settings.max_number_of_iterations_with_no_improvements) { - this->get_status() = ITERATIONS_EXHAUSTED; return true; + this->get_status() = lp_status::ITERATIONS_EXHAUSTED; return true; } if (this->total_iterations() >= this->m_settings.max_total_number_of_iterations) { - this->get_status() = ITERATIONS_EXHAUSTED; return true; + this->get_status() = lp_status::ITERATIONS_EXHAUSTED; return true; } return false; } diff --git a/src/util/lp/lp_primal_core_solver_tableau.hpp b/src/util/lp/lp_primal_core_solver_tableau.hpp index d2ce78472..3cacd2dbb 100644 --- a/src/util/lp/lp_primal_core_solver_tableau.hpp +++ b/src/util/lp/lp_primal_core_solver_tableau.hpp @@ -20,7 +20,7 @@ template void lp_primal_core_solver::advance_on_e X t; int leaving = find_leaving_and_t_tableau(entering, t); if (leaving == -1) { - this->set_status(UNBOUNDED); + this->set_status(lp_status::UNBOUNDED); return; } advance_on_entering_and_leaving_tableau(entering, leaving, t); @@ -85,12 +85,12 @@ template unsigned lp_primal_core_solver::solve_with_tableau() { init_run_tableau(); if (this->current_x_is_feasible() && this->m_look_for_feasible_solution_only) { - this->set_status(FEASIBLE); + this->set_status(lp_status::FEASIBLE); return 0; } if ((!numeric_traits::precise()) && this->A_mult_x_is_off()) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); return 0; } do { @@ -102,8 +102,8 @@ unsigned lp_primal_core_solver::solve_with_tableau() { else one_iteration_tableau(); switch (this->get_status()) { - case OPTIMAL: // double check that we are at optimum - case INFEASIBLE: + case lp_status::OPTIMAL: // double check that we are at optimum + case lp_status::INFEASIBLE: if (this->m_look_for_feasible_solution_only && this->current_x_is_feasible()) break; if (!numeric_traits::precise()) { @@ -112,7 +112,7 @@ unsigned lp_primal_core_solver::solve_with_tableau() { this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); @@ -120,7 +120,7 @@ unsigned lp_primal_core_solver::solve_with_tableau() { decide_on_status_when_cannot_find_entering(); break; } - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } else { // precise case if ((!this->infeasibility_costs_are_correct())) { init_reduced_costs_tableau(); // forcing recalc @@ -128,31 +128,31 @@ unsigned lp_primal_core_solver::solve_with_tableau() { decide_on_status_when_cannot_find_entering(); break; } - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } } break; - case TENTATIVE_UNBOUNDED: + case lp_status::TENTATIVE_UNBOUNDED: this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); break; - case UNBOUNDED: + case lp_status::UNBOUNDED: if (this->current_x_is_infeasible()) { init_reduced_costs(); - this->set_status(UNKNOWN); + this->set_status(lp_status::UNKNOWN); } break; - case UNSTABLE: + case lp_status::UNSTABLE: lp_assert(! (numeric_traits::precise())); this->init_lu(); if (this->m_factorization->get_status() != LU_status::OK) { - this->set_status(FLOATING_POINT_ERROR); + this->set_status(lp_status::FLOATING_POINT_ERROR); break; } init_reduced_costs(); @@ -161,13 +161,13 @@ unsigned lp_primal_core_solver::solve_with_tableau() { default: break; // do nothing } - } while (this->get_status() != FLOATING_POINT_ERROR + } while (this->get_status() != lp_status::FLOATING_POINT_ERROR && - this->get_status() != UNBOUNDED + this->get_status() != lp_status::UNBOUNDED && - this->get_status() != OPTIMAL + this->get_status() != lp_status::OPTIMAL && - this->get_status() != INFEASIBLE + this->get_status() != lp_status::INFEASIBLE && this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements && @@ -175,7 +175,7 @@ unsigned lp_primal_core_solver::solve_with_tableau() { && !(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only)); - lp_assert(this->get_status() == FLOATING_POINT_ERROR + lp_assert(this->get_status() == lp_status::FLOATING_POINT_ERROR || this->current_x_is_feasible() == false || diff --git a/src/util/lp/lp_primal_simplex.hpp b/src/util/lp/lp_primal_simplex.hpp index a09cd714f..759095355 100644 --- a/src/util/lp/lp_primal_simplex.hpp +++ b/src/util/lp/lp_primal_simplex.hpp @@ -216,7 +216,7 @@ template void lp_primal_simplex::fill_A_x_and_bas template void lp_primal_simplex::solve_with_total_inf() { int total_vars = this->m_A->column_count() + this->row_count(); if (total_vars == 0) { - this->m_status = OPTIMAL; + this->m_status = lp_status::OPTIMAL; return; } m_low_bounds.clear(); diff --git a/src/util/lp/lp_settings.h b/src/util/lp/lp_settings.h index 3b6b44614..3530a13f5 100644 --- a/src/util/lp/lp_settings.h +++ b/src/util/lp/lp_settings.h @@ -36,7 +36,7 @@ enum class simplex_strategy_enum { std::string column_type_to_string(column_type t); -enum lp_status { +enum class lp_status { UNKNOWN, INFEASIBLE, TENTATIVE_UNBOUNDED, diff --git a/src/util/lp/lp_settings.hpp b/src/util/lp/lp_settings.hpp index b07395222..fd5d8d8ea 100644 --- a/src/util/lp/lp_settings.hpp +++ b/src/util/lp/lp_settings.hpp @@ -21,18 +21,18 @@ std::string column_type_to_string(column_type t) { const char* lp_status_to_string(lp_status status) { switch (status) { - case UNKNOWN: return "UNKNOWN"; - case INFEASIBLE: return "INFEASIBLE"; - case UNBOUNDED: return "UNBOUNDED"; - case TENTATIVE_DUAL_UNBOUNDED: return "TENTATIVE_DUAL_UNBOUNDED"; - case DUAL_UNBOUNDED: return "DUAL_UNBOUNDED"; - case OPTIMAL: return "OPTIMAL"; - case FEASIBLE: return "FEASIBLE"; - case FLOATING_POINT_ERROR: return "FLOATING_POINT_ERROR"; - case TIME_EXHAUSTED: return "TIME_EXHAUSTED"; - case ITERATIONS_EXHAUSTED: return "ITERATIONS_EXHAUSTED"; - case EMPTY: return "EMPTY"; - case UNSTABLE: return "UNSTABLE"; + case lp_status::UNKNOWN: return "UNKNOWN"; + case lp_status::INFEASIBLE: return "INFEASIBLE"; + case lp_status::UNBOUNDED: return "UNBOUNDED"; + case lp_status::TENTATIVE_DUAL_UNBOUNDED: return "TENTATIVE_DUAL_UNBOUNDED"; + case lp_status::DUAL_UNBOUNDED: return "DUAL_UNBOUNDED"; + case lp_status::OPTIMAL: return "OPTIMAL"; + case lp_status::FEASIBLE: return "FEASIBLE"; + case lp_status::FLOATING_POINT_ERROR: return "FLOATING_POINT_ERROR"; + case lp_status::TIME_EXHAUSTED: return "TIME_EXHAUSTED"; + case lp_status::ITERATIONS_EXHAUSTED: return "ITERATIONS_EXHAUSTED"; + case lp_status::EMPTY: return "EMPTY"; + case lp_status::UNSTABLE: return "UNSTABLE"; default: lp_unreachable(); } diff --git a/src/util/lp/lp_solver.hpp b/src/util/lp/lp_solver.hpp index a903421fd..3c7f35587 100644 --- a/src/util/lp/lp_solver.hpp +++ b/src/util/lp/lp_solver.hpp @@ -223,7 +223,7 @@ template bool lp_solver::row_e_is_obsolete(std T rs = m_constraints[row_index].m_rs; if (row_is_zero(row)) { if (!is_zero(rs)) - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } @@ -233,7 +233,7 @@ template bool lp_solver::row_e_is_obsolete(std T diff = low_bound - rs; if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)){ // low_bound > rs + m_settings.refactor_epsilon - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } if (val_is_smaller_than_eps(-diff, m_settings.refactor_tolerance)){ @@ -248,7 +248,7 @@ template bool lp_solver::row_e_is_obsolete(std T diff = rs - upper_bound; if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)) { // upper_bound < rs - m_settings.refactor_tolerance - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } if (val_is_smaller_than_eps(-diff, m_settings.refactor_tolerance)){ @@ -264,7 +264,7 @@ template bool lp_solver::row_ge_is_obsolete(std: T rs = m_constraints[row_index].m_rs; if (row_is_zero(row)) { if (rs > zero_of_type()) - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } @@ -273,7 +273,7 @@ template bool lp_solver::row_ge_is_obsolete(std: T diff = rs - upper_bound; if (!val_is_smaller_than_eps(diff, m_settings.refactor_tolerance)) { // upper_bound < rs - m_settings.refactor_tolerance - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } if (val_is_smaller_than_eps(-diff, m_settings.refactor_tolerance)){ @@ -290,7 +290,7 @@ template bool lp_solver::row_le_is_obsolete(std:: T rs = m_constraints[row_index].m_rs; if (row_is_zero(row)) { if (rs < zero_of_type()) - m_status = INFEASIBLE; + m_status = lp_status::INFEASIBLE; return true; } diff --git a/src/util/lp/quick_xplain.cpp b/src/util/lp/quick_xplain.cpp index 93e40ea71..53c7ecfca 100644 --- a/src/util/lp/quick_xplain.cpp +++ b/src/util/lp/quick_xplain.cpp @@ -29,7 +29,7 @@ void quick_xplain::copy_constraint_and_add_constraint_vars(const lar_constraint& bool quick_xplain::infeasible() { m_qsol.solve(); - return m_qsol.get_status() == INFEASIBLE; + return m_qsol.get_status() == lp_status::INFEASIBLE; } // u - unexplored constraints @@ -100,7 +100,7 @@ bool quick_xplain::is_feasible(const vector & x, unsigned k) const { l.add_constraint(ls, c.m_kind, c.m_right_side); } l.solve(); - return l.get_status() != INFEASIBLE; + return l.get_status() != lp_status::INFEASIBLE; } bool quick_xplain::x_is_minimal() const { @@ -127,7 +127,7 @@ void quick_xplain::solve() { for (unsigned i : m_x) add_constraint_to_qsol(i); m_qsol.solve(); - lp_assert(m_qsol.get_status() == INFEASIBLE); + lp_assert(m_qsol.get_status() == lp_status::INFEASIBLE); m_qsol.get_infeasibility_explanation(m_explanation); lp_assert(m_qsol.explanation_is_correct(m_explanation)); lp_assert(x_is_minimal()); From 69d6b022b8535fce5b48234326fcbba073e0fbb4 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 10 Jul 2017 22:14:56 -0700 Subject: [PATCH 138/159] speed up in get_model and fix in git_model_do_not_care_... Signed-off-by: Lev Nachmanson --- src/util/lp/int_solver.cpp | 36 +++++++++++++++++++----------------- src/util/lp/lar_solver.cpp | 7 +++++-- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index 46d46e981..176d67733 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -39,24 +39,26 @@ void int_solver::failed() { } void int_solver::trace_inf_rows() const { - unsigned num = m_lar_solver->A_r().column_count(); - for (unsigned v = 0; v < num; v++) { - if (is_int(v) && !get_value(v).is_int()) { - display_column(tout, v); - } - } + TRACE("arith_int_rows", + unsigned num = m_lar_solver->A_r().column_count(); + for (unsigned v = 0; v < num; v++) { + if (is_int(v) && !get_value(v).is_int()) { + display_column(tout, v); + } + } - num = 0; - for (unsigned i = 0; i < m_lar_solver->A_r().row_count(); i++) { - unsigned j = m_lar_solver->m_mpq_lar_core_solver.m_r_basis[i]; - if (column_is_int_inf(j)) { - num++; - iterator_on_row it(m_lar_solver->A_r().m_rows[i]); - m_lar_solver->print_linear_iterator(&it, tout); - tout << "\n"; - } - } - tout << "num of int infeasible: " << num << "\n"; + num = 0; + for (unsigned i = 0; i < m_lar_solver->A_r().row_count(); i++) { + unsigned j = m_lar_solver->m_mpq_lar_core_solver.m_r_basis[i]; + if (column_is_int_inf(j)) { + num++; + iterator_on_row it(m_lar_solver->A_r().m_rows[i]); + m_lar_solver->print_linear_iterator(&it, tout); + tout << "\n"; + } + } + tout << "num of int infeasible: " << num << "\n"; + ); } int int_solver::find_inf_int_base_column() { diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index 8dcd5a327..3cef85ce2 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -368,7 +368,6 @@ void lar_solver::pop(unsigned k) { unsigned m = A_r().row_count(); clean_popped_elements(m, m_rows_with_changed_bounds); clean_inf_set_of_r_solver_after_pop(); - m_status = m_mpq_lar_core_solver.m_r_solver.current_x_is_feasible()? lp_status::OPTIMAL: lp_status::UNKNOWN; lp_assert(m_settings.simplex_strategy() == simplex_strategy_enum::undecided || (!use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); @@ -389,6 +388,8 @@ void lar_solver::pop(unsigned k) { m_settings.simplex_strategy() = m_simplex_strategy; lp_assert(sizes_are_correct()); lp_assert((!m_settings.use_tableau()) || m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); + m_status = m_mpq_lar_core_solver.m_r_solver.current_x_is_feasible()? lp_status::OPTIMAL: lp_status::UNKNOWN; + } vector lar_solver::get_all_constraint_indices() const { @@ -1139,9 +1140,11 @@ void lar_solver::get_model(std::unordered_map & variable_values) } void lar_solver::get_model_do_not_care_about_diff_vars(std::unordered_map & variable_values) const { + mpq delta = mpq(1); + delta = m_mpq_lar_core_solver.find_delta_for_strict_bounds(delta); for (unsigned i = 0; i < m_mpq_lar_core_solver.m_r_x.size(); i++ ) { const impq & rp = m_mpq_lar_core_solver.m_r_x[i]; - variable_values[i] = rp.x + rp.y; + variable_values[i] = rp.x + delta * rp.y; } } From 0e45777104e6da51ca717d1950bd8cbb72657857 Mon Sep 17 00:00:00 2001 From: Jack Feser Date: Tue, 11 Jul 2017 14:41:54 -0400 Subject: [PATCH 139/159] add get_num_scopes to python solver api --- src/api/python/z3/z3.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/api/python/z3/z3.py b/src/api/python/z3/z3.py index 9a1ebccf6..a16c1b92b 100644 --- a/src/api/python/z3/z3.py +++ b/src/api/python/z3/z3.py @@ -6054,6 +6054,24 @@ class Solver(Z3PPObject): """ Z3_solver_pop(self.ctx.ref(), self.solver, num) + def num_scopes(self): + """Return the current number of backtracking points. + + >>> s = Solver() + >>> s.num_scopes() + 0L + >>> s.push() + >>> s.num_scopes() + 1L + >>> s.push() + >>> s.num_scopes() + 2L + >>> s.pop() + >>> s.num_scopes() + 1L + """ + return Z3_solver_get_num_scopes(self.ctx.ref(), self.solver) + def reset(self): """Remove all asserted constraints and backtracking points created using `push()`. From fc6a876845a414e8591919ea18ad81304703ab2c Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Tue, 11 Jul 2017 13:38:59 -0700 Subject: [PATCH 140/159] start gomory cut Signed-off-by: Lev Nachmanson --- src/smt/theory_lra.cpp | 5 +++ src/util/lp/int_solver.cpp | 79 ++++++++++++++++++++++++-------------- src/util/lp/int_solver.h | 9 ++++- 3 files changed, 64 insertions(+), 29 deletions(-) diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index e2b4ea944..b0404e126 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -1252,6 +1252,11 @@ namespace smt { // SAT core assigns a value to return l_false; } + case lp::lia_move::bound: { + // todo nikolaj + // Need to set a bound >= k on the only var from the term + return l_false; + } case lp::lia_move::cut: { // m_explanation implies term <= k app_ref b = mk_bound(term, k); diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index 176d67733..c4c477dfb 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -110,26 +110,21 @@ int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { } -bool int_solver::mk_gomory_cut(unsigned row_index, explanation & ex) { + /** + \brief Create bounds for (non base) free vars in the given row. + Return true if at least one variable was constrained. + This method is used to enable the application of gomory cuts. + */ - auto row_it = m_lar_solver->get_iterator_on_row(row_index); + + +lia_move int_solver::mk_gomory_cut(explanation & ex) { + + lp_assert(column_is_int_inf(m_gomory_cut_inf_column)); + + return lia_move::give_up; - unsigned x_i = m_lar_solver->get_base_column_in_row(row_index); - - lp_assert(column_is_int_inf(x_i)); /* - SASSERT(is_int(x_i)); - // The following assertion is wrong. It may be violated in mixed-real-interger problems. - // The check is_gomory_cut_target will discard rows where any variable contains infinitesimals. - // SASSERT(m_value[x_i].is_rational()); // infinitesimals are not used for integer variables - SASSERT(!m_value[x_i].is_int()); // the base variable is not assigned to an integer value. - - if (constrain_free_vars(r) || !is_gomory_cut_target(r)) { - TRACE("gomory_cut", tout << "failed to apply gomory cut:\n"; - tout << "constrain_free_vars(r): " << constrain_free_vars(r) << "\n";); - return false; - } - TRACE("gomory_cut", tout << "applying cut at:\n"; display_row_info(tout, r);); antecedents ante(*this); @@ -287,9 +282,6 @@ bool int_solver::mk_gomory_cut(unsigned row_index, explanation & ex) { ante.eqs().size(), ante.eqs().c_ptr(), ante, l))); return true; */ - delete row_it; - return true; - } void int_solver::init_check_data() { @@ -299,9 +291,35 @@ void int_solver::init_check_data() { m_old_values_data.resize(n); } +int int_solver::find_next_free_var_in_gomory_row() { + lp_assert(m_iter_on_gomory_row != nullptr); + unsigned j; + while(m_iter_on_gomory_row->next(j)) { + if (is_free(j)) + return static_cast(j); + } + return -1; +} + +lia_move int_solver::proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex) { + int j = find_next_free_var_in_gomory_row(); + if (j != -1) { + lp_assert(t.is_empty()); + t.add_to_map(j, mpq(1)); + k = zero_of_type(); + return lia_move::bound; + } + delete m_iter_on_gomory_row; + m_iter_on_gomory_row = nullptr; + return mk_gomory_cut(ex); + } + + lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { - lp_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); - lp_assert(is_feasible()); + if (m_iter_on_gomory_row != nullptr) { + return proceed_with_gomory_cut(t, k, ex); + } + init_check_data(); lp_assert(inf_int_set_is_correct()); // currently it is a reimplementation of @@ -333,13 +351,12 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { } int j = find_inf_int_base_column(); if (j != -1) { + // setup the call for gomory cut TRACE("arith_int", tout << "j = " << j << " does not have an integer assignment: " << get_value(j) << "\n";); unsigned row_index = m_lar_solver->m_mpq_lar_core_solver.m_r_heading[j]; - if (!mk_gomory_cut(row_index, ex)) { - return lia_move::give_up; - // silent failure - } - return lia_move::cut; + m_iter_on_gomory_row = m_lar_solver->get_iterator_on_row(row_index); + m_gomory_cut_inf_column = j; + return check(t, k, ex); } } else { @@ -623,7 +640,8 @@ linear_combination_iterator * int_solver::get_column_iterator(unsigned j) { int_solver::int_solver(lar_solver* lar_slv) : m_lar_solver(lar_slv), - m_branch_cut_counter(0) { + m_branch_cut_counter(0), + m_iter_on_gomory_row(nullptr) { lp_assert(m_old_values_set.size() == 0); m_old_values_set.resize(lar_slv->A_r().column_count()); m_old_values_data.resize(lar_slv->A_r().column_count(), zero_of_type()); @@ -810,6 +828,11 @@ bool int_solver::is_boxed(unsigned j) const { return m_lar_solver->m_mpq_lar_core_solver.m_column_types[j] == column_type::boxed; } +bool int_solver::is_free(unsigned j) const { + return m_lar_solver->m_mpq_lar_core_solver.m_column_types[j] == column_type::free_column; +} + + lp_settings& int_solver::settings() { return m_lar_solver->settings(); } diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index 1d1a1dc69..1ae0ecbd8 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -18,6 +18,7 @@ enum class lia_move { branch, cut, conflict, + bound, give_up }; @@ -33,6 +34,8 @@ public: vector m_old_values_data; int_set m_inf_int_set; unsigned m_branch_cut_counter; + linear_combination_iterator* m_iter_on_gomory_row; + unsigned m_gomory_cut_inf_column; // methods int_solver(lar_solver* lp); // main function to check that solution provided by lar_solver is valid for integral values, @@ -80,6 +83,7 @@ private: bool is_int(unsigned j) const; bool is_base(unsigned j) const; bool is_boxed(unsigned j) const; + bool is_free(unsigned j) const; bool value_is_int(unsigned j) const; void set_value_for_nbasic_column(unsigned j, const impq & new_val); void fix_non_base_columns(); @@ -97,7 +101,10 @@ private: lp_settings& settings(); void move_non_base_vars_to_bounds(); void branch_infeasible_int_var(unsigned); - bool mk_gomory_cut(unsigned row_index, explanation & ex); + lia_move mk_gomory_cut(explanation & ex); void init_check_data(); + bool constrain_free_vars(linear_combination_iterator * r); + lia_move proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex); + int find_next_free_var_in_gomory_row(); }; } From bac16bac85e07567b2126e7d03c53bd462532d3b Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Tue, 11 Jul 2017 13:46:46 -0700 Subject: [PATCH 141/159] start gomory cut Signed-off-by: Lev Nachmanson --- src/smt/theory_lra.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index b0404e126..e02554a3d 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -1254,7 +1254,7 @@ namespace smt { } case lp::lia_move::bound: { // todo nikolaj - // Need to set a bound >= k on the only var from the term + // Need to set a bound x[j] >= k where j is the only var from the term return l_false; } case lp::lia_move::cut: { From 2056404ed488b0ffd1994a22558b2eaf21493eb5 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Tue, 11 Jul 2017 16:44:04 -0700 Subject: [PATCH 142/159] branch on a free variable before trying Gomory cuts Signed-off-by: Lev Nachmanson --- src/smt/theory_arith_int.h | 2 +- src/smt/theory_lra.cpp | 5 ---- src/util/lp/int_solver.cpp | 60 +++++++++++++++++++++++++++++++------- src/util/lp/int_solver.h | 5 +++- 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/smt/theory_arith_int.h b/src/smt/theory_arith_int.h index ca3a485c6..7be5650c6 100644 --- a/src/smt/theory_arith_int.h +++ b/src/smt/theory_arith_int.h @@ -1387,7 +1387,7 @@ namespace smt { m_branch_cut_counter++; // TODO: add giveup code - if (m_branch_cut_counter % m_params.m_arith_branch_cut_ratio == 0) { + if (true || m_branch_cut_counter % m_params.m_arith_branch_cut_ratio == 0) { // remove true :todo TRACE("opt_verbose", display(tout);); move_non_base_vars_to_bounds(); if (!make_feasible()) { diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index e02554a3d..e2b4ea944 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -1252,11 +1252,6 @@ namespace smt { // SAT core assigns a value to return l_false; } - case lp::lia_move::bound: { - // todo nikolaj - // Need to set a bound x[j] >= k where j is the only var from the term - return l_false; - } case lp::lia_move::cut: { // m_explanation implies term <= k app_ref b = mk_bound(term, k); diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index c4c477dfb..62bdc0e32 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -110,13 +110,23 @@ int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { } - /** - \brief Create bounds for (non base) free vars in the given row. - Return true if at least one variable was constrained. - This method is used to enable the application of gomory cuts. - */ +bool int_solver::is_gomory_cut_target() { + m_iter_on_gomory_row->reset(); + unsigned j; + TRACE("gomory_cut", m_lar_solver->print_linear_iterator(m_iter_on_gomory_row, tout);); - + while (m_iter_on_gomory_row->next(j)) { + // All non base variables must be at their bounds and assigned to rationals (that is, infinitesimals are not allowed). + if (j != m_gomory_cut_inf_column && (!at_bound(j) || !is_zero(get_value(j).y))) { + TRACE("gomory_cut", tout << "row is not gomory cut target:\n"; + display_column(tout, j); + tout << "at_bound: " << at_bound(j) << "\n"; + tout << "infinitesimal: " << !is_zero(get_value(j).y) << "\n";); + return false; + } + } + return true; +} lia_move int_solver::mk_gomory_cut(explanation & ex) { @@ -295,7 +305,7 @@ int int_solver::find_next_free_var_in_gomory_row() { lp_assert(m_iter_on_gomory_row != nullptr); unsigned j; while(m_iter_on_gomory_row->next(j)) { - if (is_free(j)) + if (j != m_gomory_cut_inf_column && is_free(j)) return static_cast(j); } return -1; @@ -304,11 +314,19 @@ int int_solver::find_next_free_var_in_gomory_row() { lia_move int_solver::proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex) { int j = find_next_free_var_in_gomory_row(); if (j != -1) { + m_found_free_var_in_gomory_row = true; lp_assert(t.is_empty()); t.add_to_map(j, mpq(1)); k = zero_of_type(); - return lia_move::bound; + return lia_move::branch; // branch on a free column } + if (m_found_free_var_in_gomory_row || !is_gomory_cut_target()) { + m_found_free_var_in_gomory_row = false; + delete m_iter_on_gomory_row; + m_iter_on_gomory_row = nullptr; + return lia_move::continue_with_check; + } + delete m_iter_on_gomory_row; m_iter_on_gomory_row = nullptr; return mk_gomory_cut(ex); @@ -317,7 +335,9 @@ lia_move int_solver::proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& e lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { if (m_iter_on_gomory_row != nullptr) { - return proceed_with_gomory_cut(t, k, ex); + auto ret = proceed_with_gomory_cut(t, k, ex); + if (ret != lia_move::continue_with_check) + return ret; } init_check_data(); @@ -343,7 +363,7 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { return lia_move::ok; - if ((++m_branch_cut_counter) % settings().m_int_branch_cut_threshold == 0) { + if (true || (++m_branch_cut_counter) % settings().m_int_branch_cut_threshold == 0) { move_non_base_vars_to_bounds(); lp_status st = m_lar_solver->find_feasible_solution(); if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) { @@ -641,7 +661,8 @@ linear_combination_iterator * int_solver::get_column_iterator(unsigned j) { int_solver::int_solver(lar_solver* lar_slv) : m_lar_solver(lar_slv), m_branch_cut_counter(0), - m_iter_on_gomory_row(nullptr) { + m_iter_on_gomory_row(nullptr), + m_found_free_var_in_gomory_row(false) { lp_assert(m_old_values_set.size() == 0); m_old_values_set.resize(lar_slv->A_r().column_count()); m_old_values_data.resize(lar_slv->A_r().column_count(), zero_of_type()); @@ -832,6 +853,23 @@ bool int_solver::is_free(unsigned j) const { return m_lar_solver->m_mpq_lar_core_solver.m_column_types[j] == column_type::free_column; } +bool int_solver::at_bound(unsigned j) const { + auto & mpq_solver = m_lar_solver->m_mpq_lar_core_solver.m_r_solver; + switch (mpq_solver.m_column_types[j] ) { + case column_type::boxed: + return + mpq_solver.m_low_bounds[j] == get_value(j) || + mpq_solver.m_upper_bounds[j] == get_value(j); + case column_type::low_bound: + return mpq_solver.m_low_bounds[j] == get_value(j); + case column_type::upper_bound: + return mpq_solver.m_upper_bounds[j] == get_value(j); + default: + return false; + } +} + + lp_settings& int_solver::settings() { return m_lar_solver->settings(); diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index 1ae0ecbd8..b4179fe9a 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -18,7 +18,7 @@ enum class lia_move { branch, cut, conflict, - bound, + continue_with_check, give_up }; @@ -36,6 +36,7 @@ public: unsigned m_branch_cut_counter; linear_combination_iterator* m_iter_on_gomory_row; unsigned m_gomory_cut_inf_column; + bool m_found_free_var_in_gomory_row; // methods int_solver(lar_solver* lp); // main function to check that solution provided by lar_solver is valid for integral values, @@ -106,5 +107,7 @@ private: bool constrain_free_vars(linear_combination_iterator * r); lia_move proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex); int find_next_free_var_in_gomory_row(); + bool is_gomory_cut_target(); + bool at_bound(unsigned j) const; }; } From 89c8f1722f33556def93aa54c92c3f2e3141014e Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Wed, 12 Jul 2017 12:53:10 +0100 Subject: [PATCH 143/159] Fix typo that prevented uses of `bvsmod_i` being parsed. --- src/ast/bv_decl_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/bv_decl_plugin.cpp b/src/ast/bv_decl_plugin.cpp index 03b4fe637..321943c72 100644 --- a/src/ast/bv_decl_plugin.cpp +++ b/src/ast/bv_decl_plugin.cpp @@ -732,7 +732,7 @@ void bv_decl_plugin::get_op_names(svector & op_names, symbol const op_names.push_back(builtin_name("bvudiv_i", OP_BUDIV_I)); op_names.push_back(builtin_name("bvsrem_i", OP_BSREM_I)); op_names.push_back(builtin_name("bvurem_i", OP_BUREM_I)); - op_names.push_back(builtin_name("bvumod_i", OP_BSMOD_I)); + op_names.push_back(builtin_name("bvsmod_i", OP_BSMOD_I)); op_names.push_back(builtin_name("ext_rotate_left",OP_EXT_ROTATE_LEFT)); op_names.push_back(builtin_name("ext_rotate_right",OP_EXT_ROTATE_RIGHT)); From 5b511f12b3465fa1e2757cee3b500f524f50856a Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Wed, 12 Jul 2017 13:07:19 +0100 Subject: [PATCH 144/159] Fix minor typo in C API documentation --- src/api/z3_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 505302dc1..8d53c9255 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -421,7 +421,7 @@ typedef enum It has the same semantics as Z3_OP_BUREM, but created in a context where the second operand can be assumed to be non-zero. - Z3_OP_BSMOD_I: Binary signed modulus. - It has the same semantics as Z3_OP_BSMOND, but created in a context where the second operand can be assumed to be non-zero. + It has the same semantics as Z3_OP_BSMOD, but created in a context where the second operand can be assumed to be non-zero. - Z3_OP_PR_UNDEF: Undef/Null proof object. From 8750da1da7f04f17be650cd440a594f6f93da02c Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Wed, 12 Jul 2017 16:43:10 -0700 Subject: [PATCH 145/159] progress in gomory cut Signed-off-by: Lev Nachmanson --- src/smt/theory_lra.cpp | 2 + src/util/lp/int_solver.cpp | 221 +++++++++++++++++++++---------------- src/util/lp/int_solver.h | 20 ++++ src/util/lp/lar_solver.h | 4 +- 4 files changed, 149 insertions(+), 98 deletions(-) diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index e2b4ea944..c5da28df2 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -105,6 +105,7 @@ namespace lp_api { unsigned m_bound_propagations1; unsigned m_bound_propagations2; unsigned m_assert_diseq; + unsigned m_gomory_cuts; stats() { reset(); } void reset() { memset(this, 0, sizeof(*this)); @@ -1253,6 +1254,7 @@ namespace smt { return l_false; } case lp::lia_move::cut: { + ++m_stats.m_gomory_cuts; // m_explanation implies term <= k app_ref b = mk_bound(term, k); m_eqs.reset(); diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index 62bdc0e32..56037c841 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -5,6 +5,7 @@ #include "util/lp/int_solver.h" #include "util/lp/lar_solver.h" +#include "util/lp/antecedents.h" namespace lp { void int_solver::fix_non_base_columns() { @@ -128,108 +129,107 @@ bool int_solver::is_gomory_cut_target() { return true; } + +void int_solver::is_real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, buffer & pol) { + mpq f_0 = fractional_part(get_value(m_gomory_cut_inf_column)); + mpq new_a; + if (at_lower(x_j)) { + if (a.is_pos()) { + new_a = a / (mpq(1) - f_0); + } + else { + new_a = a / f_0; + new_a.neg(); + } + k += lower_bound(x_j).x * k; // k.addmul(new_a, lower_bound(x_j).x); // is it a faster operation + // lower(x_j)->push_justification(ante, new_a, coeffs_enabled());*/ + } + else { + lp_assert(at_upper(x_j)); + if (a.is_pos()) { + new_a = a / f_0; + new_a.neg(); // the upper terms are inverted. + } + else { + new_a = a / (mpq(1) - f_0); + } + k += upper_bound(x_j).x * k; // k.addmul(new_a, upper_bound(x_j).get_rational()); + // upper(x_j)->push_justification(ante, new_a, coeffs_enabled());*/ + } + TRACE("gomory_cut_detail", tout << a << "*v" << x_j << " k: " << k << "\n";); + pol.push_back(row_entry(new_a, x_j)); +} +void int_solver::int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, buffer & pol) { + /* + ++num_ints; + SASSERT(is_int(x_j)); + mpq f_j = Ext::fractional_part(a); + TRACE("gomory_cut_detail", + tout << a << "*v" << x_j << "\n"; + tout << "fractional_part: " << Ext::fractional_part(a) << "\n"; + tout << "f_j: " << f_j << "\n"; + tout << "f_0: " << f_0 << "\n"; + tout << "one_minus_f_0: " << one_minus_f_0 << "\n";); + if (!f_j.is_zero()) { + mpq new_a; + if (at_lower(x_j)) { + if (f_j <= one_minus_f_0) { + new_a = f_j / one_minus_f_0; + } + else { + new_a = (mpq(1) - f_j) / f_0; + } + k.addmul(new_a, lower_bound(x_j).get_rational()); + lower(x_j)->push_justification(ante, new_a, coeffs_enabled()); + } + else { + SASSERT(at_upper(x_j)); + if (f_j <= f_0) { + new_a = f_j / f_0; + } + else { + new_a = (mpq(1) - f_j) / one_minus_f_0; + } + new_a.neg(); // the upper terms are inverted + k.addmul(new_a, upper_bound(x_j).get_rational()); + upper(x_j)->push_justification(ante, new_a, coeffs_enabled()); + } + TRACE("gomory_cut_detail", tout << "new_a: " << new_a << " k: " << k << "\n";); + pol.push_back(row_entry(new_a, x_j)); + lcm_den = lcm(lcm_den, denominator(new_a)); + }*/ +} + lia_move int_solver::mk_gomory_cut(explanation & ex) { lp_assert(column_is_int_inf(m_gomory_cut_inf_column)); - return lia_move::give_up; - - /* - TRACE("gomory_cut", tout << "applying cut at:\n"; display_row_info(tout, r);); + TRACE("gomory_cut", tout << "applying cut at:\n"; m_lar_solver->print_linear_iterator(m_iter_on_gomory_row, tout); tout << "\n";); - antecedents ante(*this); - - m_stats.m_gomory_cuts++; - + antecedents ante(); // gomory will be pol >= k - numeral k(1); + mpq k(1); buffer pol; - - numeral f_0 = Ext::fractional_part(m_value[x_i]); - numeral one_minus_f_0 = numeral(1) - f_0; - SASSERT(!f_0.is_zero()); - SASSERT(!one_minus_f_0.is_zero()); - - numeral lcm_den(1); + + mpq f_0 = fractional_part(get_value(m_gomory_cut_inf_column)); + mpq one_minus_f_0 = mpq(1) - f_0; + lp_assert(!is_zero(f_0) && !is_zero(one_minus_f_0)); + mpq lcm_den(1); unsigned num_ints = 0; + unsigned x_j; + mpq a; - typename vector::const_iterator it = r.begin_entries(); - typename vector::const_iterator end = r.end_entries(); - for (; it != end; ++it) { - if (!it->is_dead() && it->m_var != x_i) { - theory_var x_j = it->m_var; - numeral a_ij = it->m_coeff; - a_ij.neg(); // make the used format compatible with the format used in: Integrating Simplex with DPLL(T) - if (is_real(x_j)) { - numeral new_a_ij; - if (at_lower(x_j)) { - if (a_ij.is_pos()) { - new_a_ij = a_ij / one_minus_f_0; - } - else { - new_a_ij = a_ij / f_0; - new_a_ij.neg(); - } - k.addmul(new_a_ij, lower_bound(x_j).get_rational()); - lower(x_j)->push_justification(ante, new_a_ij, coeffs_enabled()); - } - else { - SASSERT(at_upper(x_j)); - if (a_ij.is_pos()) { - new_a_ij = a_ij / f_0; - new_a_ij.neg(); // the upper terms are inverted. - } - else { - new_a_ij = a_ij / one_minus_f_0; - } - k.addmul(new_a_ij, upper_bound(x_j).get_rational()); - upper(x_j)->push_justification(ante, new_a_ij, coeffs_enabled()); - } - TRACE("gomory_cut_detail", tout << a_ij << "*v" << x_j << " k: " << k << "\n";); - pol.push_back(row_entry(new_a_ij, x_j)); - } - else { - ++num_ints; - SASSERT(is_int(x_j)); - numeral f_j = Ext::fractional_part(a_ij); - TRACE("gomory_cut_detail", - tout << a_ij << "*v" << x_j << "\n"; - tout << "fractional_part: " << Ext::fractional_part(a_ij) << "\n"; - tout << "f_j: " << f_j << "\n"; - tout << "f_0: " << f_0 << "\n"; - tout << "one_minus_f_0: " << one_minus_f_0 << "\n";); - if (!f_j.is_zero()) { - numeral new_a_ij; - if (at_lower(x_j)) { - if (f_j <= one_minus_f_0) { - new_a_ij = f_j / one_minus_f_0; - } - else { - new_a_ij = (numeral(1) - f_j) / f_0; - } - k.addmul(new_a_ij, lower_bound(x_j).get_rational()); - lower(x_j)->push_justification(ante, new_a_ij, coeffs_enabled()); - } - else { - SASSERT(at_upper(x_j)); - if (f_j <= f_0) { - new_a_ij = f_j / f_0; - } - else { - new_a_ij = (numeral(1) - f_j) / one_minus_f_0; - } - new_a_ij.neg(); // the upper terms are inverted - k.addmul(new_a_ij, upper_bound(x_j).get_rational()); - upper(x_j)->push_justification(ante, new_a_ij, coeffs_enabled()); - } - TRACE("gomory_cut_detail", tout << "new_a_ij: " << new_a_ij << " k: " << k << "\n";); - pol.push_back(row_entry(new_a_ij, x_j)); - lcm_den = lcm(lcm_den, denominator(new_a_ij)); - } - } - } + while (m_iter_on_gomory_row->next(a, x_j)) { + if (x_j == m_gomory_cut_inf_column) + continue; + // make the format compatible with the format used in: Integrating Simplex with DPLL(T) + a.neg(); + if (is_real(x_j)) + is_real_case_in_gomory_cut(a, x_j, k, pol); + else + int_case_in_gomory_cut(a, x_j, k, pol); } - + /* CTRACE("empty_pol", pol.empty(), display_row_info(tout, r);); expr_ref bound(get_manager()); @@ -276,8 +276,8 @@ lia_move int_solver::mk_gomory_cut(explanation & ex) { } tout << "k: " << k << "\n";); } - mk_polynomial_ge(pol.size(), pol.c_ptr(), k.to_rational(), bound); - } + mk_polynomial_ge(pol.size(), pol.c_ptr(), k.to_rational(), bound); */ + /* TRACE("gomory_cut", tout << "new cut:\n" << bound << "\n"; ante.display(tout);); literal l = null_literal; context & ctx = get_context(); @@ -292,6 +292,7 @@ lia_move int_solver::mk_gomory_cut(explanation & ex) { ante.eqs().size(), ante.eqs().c_ptr(), ante, l))); return true; */ + return lia_move::give_up; } void int_solver::init_check_data() { @@ -327,9 +328,10 @@ lia_move int_solver::proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& e return lia_move::continue_with_check; } + lia_move ret = mk_gomory_cut(ex); delete m_iter_on_gomory_row; m_iter_on_gomory_row = nullptr; - return mk_gomory_cut(ex); + return ret; } @@ -792,6 +794,10 @@ bool int_solver::is_int(unsigned j) const { return m_lar_solver->column_is_int(j); } +bool int_solver::is_real(unsigned j) const { + return !is_int(j); +} + bool int_solver::value_is_int(unsigned j) const { return m_lar_solver->m_mpq_lar_core_solver.m_r_x[j].is_int(); } @@ -856,6 +862,7 @@ bool int_solver::is_free(unsigned j) const { bool int_solver::at_bound(unsigned j) const { auto & mpq_solver = m_lar_solver->m_mpq_lar_core_solver.m_r_solver; switch (mpq_solver.m_column_types[j] ) { + case column_type::fixed: case column_type::boxed: return mpq_solver.m_low_bounds[j] == get_value(j) || @@ -869,6 +876,30 @@ bool int_solver::at_bound(unsigned j) const { } } +bool int_solver::at_lower(unsigned j) const { + auto & mpq_solver = m_lar_solver->m_mpq_lar_core_solver.m_r_solver; + switch (mpq_solver.m_column_types[j] ) { + case column_type::fixed: + case column_type::boxed: + case column_type::low_bound: + return mpq_solver.m_low_bounds[j] == get_value(j); + default: + return false; + } +} + +bool int_solver::at_upper(unsigned j) const { + auto & mpq_solver = m_lar_solver->m_mpq_lar_core_solver.m_r_solver; + switch (mpq_solver.m_column_types[j] ) { + case column_type::fixed: + case column_type::boxed: + case column_type::upper_bound: + return mpq_solver.m_upper_bounds[j] == get_value(j); + default: + return false; + } +} + lp_settings& int_solver::settings() { diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index b4179fe9a..22d37d9a6 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -27,6 +27,11 @@ struct explanation { }; class int_solver { + struct row_entry { + mpq m_coeff; + unsigned m_var; + row_entry(const mpq & coeff, unsigned var) : m_coeff(coeff), m_var(var) {} + }; public: // fields lar_solver *m_lar_solver; @@ -82,6 +87,7 @@ private: const impq & lower_bound(unsigned j) const; const impq & upper_bound(unsigned j) const; bool is_int(unsigned j) const; + bool is_real(unsigned j) const; bool is_base(unsigned j) const; bool is_boxed(unsigned j) const; bool is_free(unsigned j) const; @@ -109,5 +115,19 @@ private: int find_next_free_var_in_gomory_row(); bool is_gomory_cut_target(); bool at_bound(unsigned j) const; + bool at_lower(unsigned j) const; + bool at_upper(unsigned j) const; + + inline static bool is_rational(const impq & n) { + return is_zero(n.y); + } + + inline static + mpq fractional_part(const impq & n) { + lp_assert(is_rational); + return n.x - floor(n.x); + } + void is_real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, buffer & pol); + void int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, buffer & pol); }; } diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index 2249beaa1..491bc0167 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -414,9 +414,7 @@ public: return v.is_int(); } - - - bool column_is_real(unsigned j) const { + bool column_is_real(unsigned j) const { return !column_is_int(j); } From 1931adcb74ee559cedd94fa6b68f106664e5ce90 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 13 Jul 2017 09:48:29 -0700 Subject: [PATCH 146/159] add a file Signed-off-by: Lev Nachmanson --- src/util/lp/antecedents.h | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/util/lp/antecedents.h diff --git a/src/util/lp/antecedents.h b/src/util/lp/antecedents.h new file mode 100644 index 000000000..e96c92614 --- /dev/null +++ b/src/util/lp/antecedents.h @@ -0,0 +1,10 @@ +/* + Copyright (c) 2017 Microsoft Corporation + Author: Lev Nachmanson +*/ +#pragma once + +namespace lp { +class antecedents { +}; +} From da34de340d582784e0068eb6f287faa56b74a243 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 15 Jul 2017 20:25:13 +0100 Subject: [PATCH 147/159] Fixed bug in sat model converter. Fixes #1148. --- src/sat/sat_model_converter.cpp | 27 +++++++++++++++++++++++---- src/sat/sat_model_converter.h | 7 ++++--- src/sat/sat_solver.cpp | 17 +++++++++-------- src/sat/sat_solver/inc_sat_solver.cpp | 18 +++++++++--------- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/sat/sat_model_converter.cpp b/src/sat/sat_model_converter.cpp index 8901c276f..525d084dc 100644 --- a/src/sat/sat_model_converter.cpp +++ b/src/sat/sat_model_converter.cpp @@ -32,7 +32,7 @@ namespace sat { void model_converter::reset() { m_entries.finalize(); } - + void model_converter::operator()(model & m) const { vector::const_iterator begin = m_entries.begin(); vector::const_iterator it = m_entries.end(); @@ -46,7 +46,7 @@ namespace sat { literal_vector::const_iterator it2 = it->m_clauses.begin(); literal_vector::const_iterator end2 = it->m_clauses.end(); for (; it2 != end2; ++it2) { - literal l = *it2; + literal l = *it2; if (l == null_literal) { // end of clause if (!sat) { @@ -56,6 +56,7 @@ namespace sat { sat = false; continue; } + if (sat) continue; bool sign = l.sign(); @@ -125,7 +126,7 @@ namespace sat { } return ok; } - + model_converter::entry & model_converter::mk(kind k, bool_var v) { m_entries.push_back(entry(k, v)); entry & e = m_entries.back(); @@ -218,7 +219,7 @@ namespace sat { out << *it2; } out << ")"; - } + } out << ")\n"; } @@ -237,4 +238,22 @@ namespace sat { } } + unsigned model_converter::max_var(unsigned min) const { + unsigned result = min; + vector::const_iterator it = m_entries.begin(); + vector::const_iterator end = m_entries.end(); + for (; it != end; ++it) { + literal_vector::const_iterator lvit = it->m_clauses.begin(); + literal_vector::const_iterator lvend = it->m_clauses.end(); + for (; lvit != lvend; ++lvit) { + literal l = *lvit; + if (l != null_literal) { + if (l.var() > result) + result = l.var(); + } + } + } + return result; + } + }; diff --git a/src/sat/sat_model_converter.h b/src/sat/sat_model_converter.h index b89e6e784..eb2237707 100644 --- a/src/sat/sat_model_converter.h +++ b/src/sat/sat_model_converter.h @@ -26,7 +26,7 @@ namespace sat { \brief Stores eliminated variables and Blocked clauses. It uses these clauses to extend/patch the model produced for the simplified CNF formula. - + This information may also be used to support incremental solving. If new clauses are asserted into the SAT engine, then we can restore the state by re-asserting all clauses in the model @@ -50,7 +50,7 @@ namespace sat { m_kind(src.m_kind), m_clauses(src.m_clauses) { } - bool_var var() const { return m_var; } + bool_var var() const { return m_var; } kind get_kind() const { return static_cast(m_kind); } }; private: @@ -74,8 +74,9 @@ namespace sat { void copy(model_converter const & src); void collect_vars(bool_var_set & s) const; + unsigned max_var(unsigned min) const; }; - + }; #endif diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index 7f2b75830..fbfa0ec6b 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -2628,7 +2628,7 @@ namespace sat { unsigned j = 0; for (unsigned i = 0; i < clauses.size(); ++i) { clause & c = *(clauses[i]); - if (c.contains(lit)) { + if (c.contains(lit) || c.contains(~lit)) { detach_clause(c); del_clause(c); } @@ -2684,6 +2684,7 @@ namespace sat { w = max_var(m_clauses, w); w = max_var(true, w); w = max_var(false, w); + v = m_mc.max_var(w); for (unsigned i = 0; i < m_trail.size(); ++i) { if (m_trail[i].var() > w) w = m_trail[i].var(); } @@ -3150,9 +3151,9 @@ namespace sat { } } } - + // Algorithm 7: Corebased Algorithm with Chunking - + static void back_remove(sat::literal_vector& lits, sat::literal l) { for (unsigned i = lits.size(); i > 0; ) { --i; @@ -3176,7 +3177,7 @@ namespace sat { } } } - + static lbool core_chunking(sat::solver& s, model const& m, sat::bool_var_vector const& vars, sat::literal_vector const& asms, vector& conseq, unsigned K) { sat::literal_vector lambda; for (unsigned i = 0; i < vars.size(); i++) { @@ -3375,7 +3376,7 @@ namespace sat { if (check_inconsistent()) return l_false; unsigned num_iterations = 0; - extract_fixed_consequences(unfixed_lits, assumptions, unfixed_vars, conseq); + extract_fixed_consequences(unfixed_lits, assumptions, unfixed_vars, conseq); update_unfixed_literals(unfixed_lits, unfixed_vars); while (!unfixed_lits.empty()) { if (scope_lvl() > 1) { @@ -3390,7 +3391,7 @@ namespace sat { unsigned num_assigned = 0; lbool is_sat = l_true; for (; it != end; ++it) { - literal lit = *it; + literal lit = *it; if (value(lit) != l_undef) { ++num_fixed; if (lvl(lit) <= 1 && value(lit) == l_true) { @@ -3445,8 +3446,8 @@ namespace sat { << " iterations: " << num_iterations << " variables: " << unfixed_lits.size() << " fixed: " << conseq.size() - << " status: " << is_sat - << " pre-assigned: " << num_fixed + << " status: " << is_sat + << " pre-assigned: " << num_fixed << " unfixed: " << lits.size() - conseq.size() - unfixed_lits.size() << ")\n";); diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index b6904ef02..baac9f37b 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -131,7 +131,7 @@ public: } bool is_literal(expr* e) const { - return + return is_uninterp_const(e) || (m.is_not(e, e) && is_uninterp_const(e)); } @@ -153,7 +153,7 @@ public: asm2fml.insert(assumptions[i], assumptions[i]); } } - + TRACE("sat", tout << _assumptions << "\n";); dep2asm_t dep2asm; m_model = 0; @@ -163,7 +163,7 @@ public: if (r != l_true) return r; r = m_solver.check(m_asms.size(), m_asms.c_ptr()); - + switch (r) { case l_true: if (sz > 0) { @@ -280,14 +280,14 @@ public: return r; } - // build map from bound variables to + // build map from bound variables to // the consequences that cover them. u_map bool_var2conseq; for (unsigned i = 0; i < lconseq.size(); ++i) { TRACE("sat", tout << lconseq[i] << "\n";); bool_var2conseq.insert(lconseq[i][0].var(), i); } - + // extract original fixed variables u_map asm2dep; extract_asm2dep(dep2asm, asm2dep); @@ -441,7 +441,7 @@ private: lbool internalize_vars(expr_ref_vector const& vars, sat::bool_var_vector& bvars) { for (unsigned i = 0; i < vars.size(); ++i) { - internalize_var(vars[i], bvars); + internalize_var(vars[i], bvars); } return l_true; } @@ -453,7 +453,7 @@ private: bool internalized = false; if (is_uninterp_const(v) && m.is_bool(v)) { sat::bool_var b = m_map.to_bool_var(v); - + if (b != sat::null_bool_var) { bvars.push_back(b); internalized = true; @@ -479,7 +479,7 @@ private: else if (is_uninterp_const(v) && bvutil.is_bv(v)) { // variable does not occur in assertions, so is unconstrained. } - CTRACE("sat", !internalized, tout << "unhandled variable " << mk_pp(v, m) << "\n";); + CTRACE("sat", !internalized, tout << "unhandled variable " << mk_pp(v, m) << "\n";); return internalized; } @@ -506,7 +506,7 @@ private: } expr_ref val(m); expr_ref_vector conj(m); - internalize_value(value, v, val); + internalize_value(value, v, val); while (!premises.empty()) { expr* e = 0; VERIFY(asm2dep.find(premises.pop().index(), e)); From 77171f4af8a995a775a6fb9fb1c6270991462442 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 17 Jul 2017 15:17:46 -0700 Subject: [PATCH 148/159] the first version of Gomory cut, probably broken Signed-off-by: Lev Nachmanson --- src/util/lp/antecedents.h | 10 -- src/util/lp/int_solver.cpp | 184 ++++++++++++++++++++----------------- src/util/lp/int_solver.h | 18 ++-- src/util/lp/lar_solver.cpp | 38 ++++---- src/util/lp/lar_solver.h | 13 ++- src/util/lp/lar_term.h | 17 +++- 6 files changed, 152 insertions(+), 128 deletions(-) delete mode 100644 src/util/lp/antecedents.h diff --git a/src/util/lp/antecedents.h b/src/util/lp/antecedents.h deleted file mode 100644 index e96c92614..000000000 --- a/src/util/lp/antecedents.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - Copyright (c) 2017 Microsoft Corporation - Author: Lev Nachmanson -*/ -#pragma once - -namespace lp { -class antecedents { -}; -} diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index 56037c841..a6eea6021 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -5,7 +5,6 @@ #include "util/lp/int_solver.h" #include "util/lp/lar_solver.h" -#include "util/lp/antecedents.h" namespace lp { void int_solver::fix_non_base_columns() { @@ -114,7 +113,9 @@ int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { bool int_solver::is_gomory_cut_target() { m_iter_on_gomory_row->reset(); unsigned j; - TRACE("gomory_cut", m_lar_solver->print_linear_iterator(m_iter_on_gomory_row, tout);); + TRACE("gomory_cut", m_lar_solver->print_linear_iterator(m_iter_on_gomory_row, tout); + m_iter_on_gomory_row->reset(); + ); while (m_iter_on_gomory_row->next(j)) { // All non base variables must be at their bounds and assigned to rationals (that is, infinitesimals are not allowed). @@ -126,23 +127,25 @@ bool int_solver::is_gomory_cut_target() { return false; } } + m_iter_on_gomory_row->reset(); return true; } -void int_solver::is_real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, buffer & pol) { +void int_solver::real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term& pol, explanation & expl) { mpq f_0 = fractional_part(get_value(m_gomory_cut_inf_column)); mpq new_a; if (at_lower(x_j)) { if (a.is_pos()) { - new_a = a / (mpq(1) - f_0); + new_a = a / (1 - f_0); } else { new_a = a / f_0; new_a.neg(); } k += lower_bound(x_j).x * k; // k.addmul(new_a, lower_bound(x_j).x); // is it a faster operation - // lower(x_j)->push_justification(ante, new_a, coeffs_enabled());*/ + + expl.push_justification(column_low_bound_constraint(x_j), new_a); } else { lp_assert(at_upper(x_j)); @@ -154,33 +157,43 @@ void int_solver::is_real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k new_a = a / (mpq(1) - f_0); } k += upper_bound(x_j).x * k; // k.addmul(new_a, upper_bound(x_j).get_rational()); - // upper(x_j)->push_justification(ante, new_a, coeffs_enabled());*/ + expl.push_justification(column_upper_bound_constraint(x_j), new_a); } TRACE("gomory_cut_detail", tout << a << "*v" << x_j << " k: " << k << "\n";); - pol.push_back(row_entry(new_a, x_j)); + pol.add_monoid(new_a, x_j); } -void int_solver::int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, buffer & pol) { - /* - ++num_ints; - SASSERT(is_int(x_j)); - mpq f_j = Ext::fractional_part(a); + +constraint_index int_solver::column_upper_bound_constraint(unsigned j) const { + return m_lar_solver->get_column_upper_bound_witness(j); +} + +constraint_index int_solver::column_low_bound_constraint(unsigned j) const { + return m_lar_solver->get_column_low_bound_witness(j); +} + + +void int_solver::int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term & pol, explanation& expl, mpq & lcm_den) { + mpq f_0 = fractional_part(get_value(m_gomory_cut_inf_column)); + lp_assert(is_int(x_j)); + mpq f_j = fractional_part(a); TRACE("gomory_cut_detail", tout << a << "*v" << x_j << "\n"; - tout << "fractional_part: " << Ext::fractional_part(a) << "\n"; + tout << "fractional_part: " << fractional_part(a) << "\n"; tout << "f_j: " << f_j << "\n"; tout << "f_0: " << f_0 << "\n"; - tout << "one_minus_f_0: " << one_minus_f_0 << "\n";); + tout << "one_minus_f_0: " << 1 - f_0 << "\n";); if (!f_j.is_zero()) { mpq new_a; if (at_lower(x_j)) { + auto one_minus_f_0 = 1 - f_0; if (f_j <= one_minus_f_0) { new_a = f_j / one_minus_f_0; } else { - new_a = (mpq(1) - f_j) / f_0; + new_a = (1 - f_j) / f_0; } - k.addmul(new_a, lower_bound(x_j).get_rational()); - lower(x_j)->push_justification(ante, new_a, coeffs_enabled()); + k.addmul(new_a, lower_bound(x_j).x); + expl.push_justification(column_low_bound_constraint(x_j), new_a); } else { SASSERT(at_upper(x_j)); @@ -188,111 +201,96 @@ void int_solver::int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, bu new_a = f_j / f_0; } else { - new_a = (mpq(1) - f_j) / one_minus_f_0; + new_a = (mpq(1) - f_j) / 1 - f_0; } new_a.neg(); // the upper terms are inverted - k.addmul(new_a, upper_bound(x_j).get_rational()); - upper(x_j)->push_justification(ante, new_a, coeffs_enabled()); + k.addmul(new_a, upper_bound(x_j).x); + expl.push_justification(column_upper_bound_constraint(x_j), new_a); } TRACE("gomory_cut_detail", tout << "new_a: " << new_a << " k: " << k << "\n";); - pol.push_back(row_entry(new_a, x_j)); + pol.add_monoid(new_a, x_j); lcm_den = lcm(lcm_den, denominator(new_a)); - }*/ + } } -lia_move int_solver::mk_gomory_cut(explanation & ex) { +lia_move int_solver::mk_gomory_cut(lar_term& t, mpq& k, explanation & expl ) { lp_assert(column_is_int_inf(m_gomory_cut_inf_column)); - TRACE("gomory_cut", tout << "applying cut at:\n"; m_lar_solver->print_linear_iterator(m_iter_on_gomory_row, tout); tout << "\n";); + TRACE("gomory_cut", tout << "applying cut at:\n"; m_lar_solver->print_linear_iterator(m_iter_on_gomory_row, tout); tout << std::endl; m_iter_on_gomory_row->reset();); - antecedents ante(); - // gomory will be pol >= k - mpq k(1); - buffer pol; - - mpq f_0 = fractional_part(get_value(m_gomory_cut_inf_column)); - mpq one_minus_f_0 = mpq(1) - f_0; - lp_assert(!is_zero(f_0) && !is_zero(one_minus_f_0)); + // gomory will be t >= k + k = 1; mpq lcm_den(1); unsigned num_ints = 0; unsigned x_j; mpq a; - while (m_iter_on_gomory_row->next(a, x_j)) { if (x_j == m_gomory_cut_inf_column) continue; // make the format compatible with the format used in: Integrating Simplex with DPLL(T) a.neg(); if (is_real(x_j)) - is_real_case_in_gomory_cut(a, x_j, k, pol); - else - int_case_in_gomory_cut(a, x_j, k, pol); + real_case_in_gomory_cut(a, x_j, k, t, expl); + else { + num_ints++; + int_case_in_gomory_cut(a, x_j, k, t, expl, lcm_den); + } } - /* - CTRACE("empty_pol", pol.empty(), display_row_info(tout, r);); - expr_ref bound(get_manager()); - if (pol.empty()) { - SASSERT(k.is_pos()); + if (t.is_empty()) { + TRACE("empty_pol", + display_row_info(tout, + m_lar_solver->m_mpq_lar_core_solver.m_r_heading[m_gomory_cut_inf_column]);); + lp_assert(k.is_pos()); // conflict 0 >= k where k is positive - set_conflict(ante, ante, "gomory-cut"); - return true; + k.neg(); // returning 0 <= -k + return lia_move::conflict; } - else if (pol.size() == 1) { - theory_var v = pol[0].m_var; - k /= pol[0].m_coeff; - bool is_lower = pol[0].m_coeff.is_pos(); - if (is_int(v) && !k.is_int()) { + + auto pol = t.coeffs_as_vector(); + if (pol.size() == 1) { + unsigned j = pol[0].second; + k /= pol[0].first; + bool is_lower = pol[0].first.is_pos(); + if (is_int(j) && !k.is_int()) { k = is_lower?ceil(k):floor(k); } - rational _k = k.to_rational(); - if (is_lower) - bound = m_util.mk_ge(get_enode(v)->get_owner(), m_util.mk_numeral(_k, is_int(v))); - else - bound = m_util.mk_le(get_enode(v)->get_owner(), m_util.mk_numeral(_k, is_int(v))); - } - else { + if (is_lower) { // returning -t <= -k which is equivalent to t >= k + k.neg(); + t.negate(); + } + } else { if (num_ints > 0) { lcm_den = lcm(lcm_den, denominator(k)); TRACE("gomory_cut_detail", tout << "k: " << k << " lcm_den: " << lcm_den << "\n"; - for (unsigned i = 0; i < pol.size(); i++) { - tout << pol[i].m_coeff << " " << pol[i].m_var << "\n"; - } - tout << "k: " << k << "\n";); + linear_combination_iterator_on_vector pi(pol); + m_lar_solver->print_linear_iterator(&pi, tout); + tout << "\nk: " << k << "\n";); SASSERT(lcm_den.is_pos()); if (!lcm_den.is_one()) { // normalize coefficients of integer parameters to be integers. - unsigned n = pol.size(); - for (unsigned i = 0; i < n; i++) { - pol[i].m_coeff *= lcm_den; - SASSERT(!is_int(pol[i].m_var) || pol[i].m_coeff.is_int()); + for (auto & pi: pol) { + pi.first *= lcm_den; + SASSERT(!is_int(pi.second) || pi.first.is_int()); } k *= lcm_den; } TRACE("gomory_cut_detail", tout << "after *lcm\n"; for (unsigned i = 0; i < pol.size(); i++) { - tout << pol[i].m_coeff << " * v" << pol[i].m_var << "\n"; + tout << pol[i].first << " * v" << pol[i].second << "\n"; } tout << "k: " << k << "\n";); + t.clear(); + // negate everything to return -pol <= -k + for (const auto & pi: pol) + t.add_monoid(-pi.first, pi.second); + k.neg(); + } else { + lp_assert(false); // not sure what happens here } - mk_polynomial_ge(pol.size(), pol.c_ptr(), k.to_rational(), bound); */ - /* - TRACE("gomory_cut", tout << "new cut:\n" << bound << "\n"; ante.display(tout);); - literal l = null_literal; - context & ctx = get_context(); - ctx.internalize(bound, true); - l = ctx.get_literal(bound); - ctx.mark_as_relevant(l); - dump_lemmas(l, ante); - ctx.assign(l, ctx.mk_justification( - gomory_cut_justification( - get_id(), ctx.get_region(), - ante.lits().size(), ante.lits().c_ptr(), - ante.eqs().size(), ante.eqs().c_ptr(), ante, l))); - return true; - */ - return lia_move::give_up; + } + return lia_move::cut; } void int_solver::init_check_data() { @@ -317,7 +315,7 @@ lia_move int_solver::proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& e if (j != -1) { m_found_free_var_in_gomory_row = true; lp_assert(t.is_empty()); - t.add_to_map(j, mpq(1)); + t.add_monoid(mpq(1), j); k = zero_of_type(); return lia_move::branch; // branch on a free column } @@ -328,7 +326,7 @@ lia_move int_solver::proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& e return lia_move::continue_with_check; } - lia_move ret = mk_gomory_cut(ex); + lia_move ret = mk_gomory_cut(t, k, ex); delete m_iter_on_gomory_row; m_iter_on_gomory_row = nullptr; return ret; @@ -387,7 +385,7 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { TRACE("arith_int", tout << "j" << j << " does not have an integer assignment: " << get_value(j) << "\n";); lp_assert(t.is_empty()); - t.add_to_map(j, mpq(1)); + t.add_monoid(1, j); k = floor(get_value(j)); TRACE("arith_int", tout << "branching v" << j << " = " << get_value(j) << "\n"; display_column(tout, j); @@ -906,4 +904,22 @@ lp_settings& int_solver::settings() { return m_lar_solver->settings(); } +void int_solver::display_row_info(std::ostream & out, unsigned row_index) const { + auto & rslv = m_lar_solver->m_mpq_lar_core_solver.m_r_solver; + auto it = m_lar_solver->get_iterator_on_row(row_index); + mpq a; + unsigned j; + while (it->next(a, j)) { + if (numeric_traits::is_pos(a)) + out << "+"; + out << a << rslv.column_name(j) << " "; + } + + it->reset(); + while(it->next(j)) { + rslv.print_column_bound_info(j, out); + } + rslv.print_column_bound_info(rslv.m_basis[row_index], out); + delete it; +} } diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index 22d37d9a6..18b44dccb 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -8,7 +8,6 @@ #include "util/lp/iterator_on_row.h" #include "util/lp/int_set.h" #include "util/lp/lar_term.h" - namespace lp { class lar_solver; template @@ -24,14 +23,12 @@ enum class lia_move { struct explanation { vector> m_explanation; + void push_justification(constraint_index j, const mpq& v) { + m_explanation.push_back(std::make_pair(v, j)); + } }; class int_solver { - struct row_entry { - mpq m_coeff; - unsigned m_var; - row_entry(const mpq & coeff, unsigned var) : m_coeff(coeff), m_var(var) {} - }; public: // fields lar_solver *m_lar_solver; @@ -108,7 +105,7 @@ private: lp_settings& settings(); void move_non_base_vars_to_bounds(); void branch_infeasible_int_var(unsigned); - lia_move mk_gomory_cut(explanation & ex); + lia_move mk_gomory_cut(lar_term& t, mpq& k,explanation & ex); void init_check_data(); bool constrain_free_vars(linear_combination_iterator * r); lia_move proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex); @@ -127,7 +124,10 @@ private: lp_assert(is_rational); return n.x - floor(n.x); } - void is_real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, buffer & pol); - void int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, buffer & pol); + void real_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term& t, explanation & ex); + void int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, lar_term& t, explanation& ex, mpq & lcm_den); + constraint_index column_upper_bound_constraint(unsigned j) const; + constraint_index column_low_bound_constraint(unsigned j) const; + void display_row_info(std::ostream & out, unsigned row_index) const; }; } diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index 3cef85ce2..451be98fe 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -237,7 +237,7 @@ void lar_solver::explain_implied_bound(implied_bound & ib, bound_propagator & bp } int a_sign = is_pos(a)? 1: -1; int sign = j_sign * a_sign; - const ul_pair & ul = m_vars_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(); lp_assert(is_valid(witness)); bp.consume(a, witness); @@ -309,7 +309,7 @@ lp_status lar_solver::solve() { void lar_solver::fill_explanation_from_infeasible_column(vector> & evidence) const{ // this is the case when the lower bound is in conflict with the upper one - const ul_pair & ul = m_vars_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::one(), ul.upper_bound_witness())); evidence.push_back(std::make_pair(-numeric_traits::one(), ul.low_bound_witness())); } @@ -325,7 +325,7 @@ vector lar_solver::get_list_of_all_var_indices() const { void lar_solver::push() { m_simplex_strategy = m_settings.simplex_strategy(); m_simplex_strategy.push(); - m_vars_to_ul_pairs.push(); + m_columns_to_ul_pairs.push(); m_infeasible_column_index.push(); m_mpq_lar_core_solver.push(); m_term_count = m_terms.size(); @@ -354,14 +354,14 @@ void lar_solver::pop(unsigned k) { int n_was = static_cast(m_ext_vars_to_columns.size()); m_infeasible_column_index.pop(k); - unsigned n = m_vars_to_ul_pairs.peek_size(k); + unsigned n = m_columns_to_ul_pairs.peek_size(k); for (unsigned j = n_was; j-- > n;) m_ext_vars_to_columns.erase(m_columns_to_ext_vars_or_term_indices[j]); m_columns_to_ext_vars_or_term_indices.resize(n); if (m_settings.use_tableau()) { pop_tableau(); } - m_vars_to_ul_pairs.pop(k); + m_columns_to_ul_pairs.pop(k); m_mpq_lar_core_solver.pop(k); clean_popped_elements(n, m_columns_with_changed_bound); @@ -531,15 +531,15 @@ void lar_solver::pop_core_solver_params(unsigned k) { void lar_solver::set_upper_bound_witness(var_index j, constraint_index ci) { - ul_pair ul = m_vars_to_ul_pairs[j]; + ul_pair ul = m_columns_to_ul_pairs[j]; ul.upper_bound_witness() = ci; - m_vars_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) { - ul_pair ul = m_vars_to_ul_pairs[j]; + ul_pair ul = m_columns_to_ul_pairs[j]; ul.low_bound_witness() = ci; - m_vars_to_ul_pairs[j] = ul; + m_columns_to_ul_pairs[j] = ul; } void lar_solver::register_one_coeff_in_map(std::unordered_map & coeffs, const mpq & a, unsigned j) { @@ -1041,11 +1041,11 @@ mpq lar_solver::sum_of_right_sides_of_explanation(const vector= m_vars_to_ul_pairs.size()) { + if (var >= m_columns_to_ul_pairs.size()) { // TBD: bounds on terms could also be used, caller may have to track these. return false; } - const ul_pair & ul = m_vars_to_ul_pairs[var]; + const ul_pair & ul = m_columns_to_ul_pairs[var]; ci = ul.low_bound_witness(); if (ci != static_cast(-1)) { auto& p = m_mpq_lar_core_solver.m_r_low_bounds()[var]; @@ -1060,11 +1060,11 @@ bool lar_solver::has_lower_bound(var_index var, constraint_index& ci, mpq& value bool lar_solver::has_upper_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) { - if (var >= m_vars_to_ul_pairs.size()) { + if (var >= m_columns_to_ul_pairs.size()) { // TBD: bounds on terms could also be used, caller may have to track these. return false; } - const ul_pair & ul = m_vars_to_ul_pairs[var]; + const ul_pair & ul = m_columns_to_ul_pairs[var]; ci = ul.upper_bound_witness(); if (ci != static_cast(-1)) { auto& p = m_mpq_lar_core_solver.m_r_upper_bounds()[var]; @@ -1105,7 +1105,7 @@ void lar_solver::get_infeasibility_explanation_for_inf_sign( unsigned j = it.second; int adj_sign = coeff.is_pos() ? inf_sign : -inf_sign; - const ul_pair & ul = m_vars_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(); lp_assert(bound_constr_i < m_constraints.size()); @@ -1238,7 +1238,7 @@ void lar_solver::pop() { } bool lar_solver::column_represents_row_in_tableau(unsigned j) { - return m_vars_to_ul_pairs()[j].m_i != static_cast(-1); + return m_columns_to_ul_pairs()[j].m_i != static_cast(-1); } void lar_solver::make_sure_that_the_bottom_right_elem_not_zero_in_tableau(unsigned i, unsigned j) { @@ -1462,9 +1462,9 @@ var_index lar_solver::add_var(unsigned ext_j, bool is_int) { if (it != m_ext_vars_to_columns.end()) { return it->second.ext_j(); } - lp_assert(m_vars_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(); - m_vars_to_ul_pairs.push_back(ul_pair(static_cast(-1))); + m_columns_to_ul_pairs.push_back(ul_pair(static_cast(-1))); add_non_basic_var_to_core_fields(ext_j, is_int); lp_assert(sizes_are_correct()); return i; @@ -1568,7 +1568,7 @@ void lar_solver::add_row_from_term_no_constraint(const lar_term * term, unsigned // j will be a new variable unsigned j = A_r().column_count(); ul_pair ul(j); - m_vars_to_ul_pairs.push_back(ul); + m_columns_to_ul_pairs.push_back(ul); add_basic_var_to_core_fields(); if (use_tableau()) { auto it = iterator_on_term_with_basis_var(*term, j); @@ -1677,7 +1677,7 @@ void lar_solver::add_constraint_from_term_and_create_new_column_row(unsigned ter void lar_solver::decide_on_strategy_and_adjust_initial_state() { lp_assert(strategy_is_undecided()); - if (m_vars_to_ul_pairs.size() > m_settings.column_number_threshold_for_using_lu_in_lar_solver) { + if (m_columns_to_ul_pairs.size() > m_settings.column_number_threshold_for_using_lu_in_lar_solver) { m_settings.simplex_strategy() = simplex_strategy_enum::lu; } else { diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index 491bc0167..9afb4180b 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -52,7 +52,7 @@ class lar_solver : public column_namer { stacked_value m_simplex_strategy; std::unordered_map m_ext_vars_to_columns; vector m_columns_to_ext_vars_or_term_indices; - stacked_vector m_vars_to_ul_pairs; + stacked_vector m_columns_to_ul_pairs; vector m_constraints; stacked_value m_constraint_count; // the set of column indices j such that bounds have changed for j @@ -433,7 +433,7 @@ public: } void get_bound_constraint_witnesses_for_column(unsigned j, constraint_index & lc, constraint_index & uc) const { - const ul_pair & ul = m_vars_to_ul_pairs[j]; + const ul_pair & ul = m_columns_to_ul_pairs[j]; lc = ul.low_bound_witness(); uc = ul.upper_bound_witness(); } @@ -453,6 +453,13 @@ public: return m_mpq_lar_core_solver.m_r_solver.get_base_column_in_row(row_index); } - + constraint_index get_column_upper_bound_witness(unsigned j) const { + return m_columns_to_ul_pairs()[j].upper_bound_witness(); + } + + constraint_index get_column_low_bound_witness(unsigned j) const { + return m_columns_to_ul_pairs()[j].low_bound_witness(); + } + }; } diff --git a/src/util/lp/lar_term.h b/src/util/lp/lar_term.h index 71320b7c3..dc3921767 100644 --- a/src/util/lp/lar_term.h +++ b/src/util/lp/lar_term.h @@ -10,7 +10,7 @@ struct lar_term { std::unordered_map m_coeffs; mpq m_v; lar_term() {} - void add_to_map(unsigned j, const mpq& c) { + void add_monoid(const mpq& c, unsigned j) { auto it = m_coeffs.find(j); if (it == m_coeffs.end()) { m_coeffs.emplace(j, c); @@ -34,7 +34,7 @@ struct lar_term { lar_term(const vector>& coeffs, const mpq & v) : m_v(v) { for (const auto & p : coeffs) { - add_to_map(p.second, p.first); + add_monoid(p.first, p.second); } } bool operator==(const lar_term & a) const { return false; } // take care not to create identical terms @@ -56,7 +56,7 @@ struct lar_term { if (it == m_coeffs.end()) return; const mpq & b = it->second; for (unsigned it_j :li.m_index) { - add_to_map(it_j, - b * li.m_data[it_j]); + add_monoid(- b * li.m_data[it_j], it_j); } m_coeffs.erase(it); } @@ -64,5 +64,16 @@ struct lar_term { bool contains(unsigned j) const { return m_coeffs.find(j) != m_coeffs.end(); } + + void negate() { + for (auto & t : m_coeffs) + t.second.neg(); + } + + void clear() { + m_coeffs.clear(); + m_v = zero_of_type(); + } + }; } From 729644a2b64a38d580f684d1cb4b53847cb56d0f Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 17 Jul 2017 16:08:20 -0700 Subject: [PATCH 149/159] fix term_is_int Signed-off-by: Lev Nachmanson --- src/util/lp/lar_solver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index 451be98fe..96313703a 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -1413,7 +1413,7 @@ bool lar_solver::model_is_int_feasible() const { bool lar_solver::term_is_int(const lar_term * t) const { for (auto const & p : t->m_coeffs) - if (!column_is_int(p.first) || p.second.is_int()) + if (! (column_is_int(p.first) && p.second.is_int())) return false; return t->m_v.is_int(); } From 94b3fee6ac297e73a9185b5f52fd0e9717cd6954 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Mon, 17 Jul 2017 16:41:02 -0700 Subject: [PATCH 150/159] rename a function Signed-off-by: Lev Nachmanson --- src/util/lp/int_solver.cpp | 1 + src/util/lp/lar_solver.cpp | 7 +++++++ src/util/lp/lar_solver.h | 4 +++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index a6eea6021..9de63a6fc 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -336,6 +336,7 @@ lia_move int_solver::proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& e lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { if (m_iter_on_gomory_row != nullptr) { auto ret = proceed_with_gomory_cut(t, k, ex); + TRACE("gomory_cut", tout << "term t = "; m_lar_solver->print_term_as_indices(t, tout);); if (ret != lia_move::continue_with_check) return ret; } diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index 96313703a..2e8631445 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -1192,6 +1192,13 @@ void lar_solver::print_term(lar_term const& term, std::ostream & out) const { print_linear_combination_of_column_indices(term.coeffs_as_vector(), out); } +void lar_solver::print_term_as_indices(lar_term const& term, std::ostream & out) const { + if (!numeric_traits::is_zero(term.m_v)) { + out << term.m_v << " + "; + } + print_linear_combination_of_column_indices_only(term.coeffs_as_vector(), out); +} + mpq lar_solver::get_left_side_val(const lar_base_constraint & cns, const std::unordered_map & var_map) const { mpq ret = cns.get_free_coeff_of_left_side(); for (auto & it : cns.get_left_side_coefficients()) { diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index 9afb4180b..46af1ae63 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -381,12 +381,14 @@ public: void print_constraints(std::ostream& out) const ; - void print_terms(std::ostream& out) const ; + void print_terms(std::ostream& out) const; void print_left_side_of_constraint(const lar_base_constraint * c, std::ostream & out) const; void print_term(lar_term const& term, std::ostream & out) const; + void print_term_as_indices(lar_term const& term, std::ostream & out) const; + mpq get_left_side_val(const lar_base_constraint & cns, const std::unordered_map & var_map) const; void print_constraint(const lar_base_constraint * c, std::ostream & out) const; From 4d1b0d8026f6ea5b53bec45013167403e0dbad07 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Wed, 19 Jul 2017 16:50:23 -0700 Subject: [PATCH 151/159] gomory cut worked on a toy example Signed-off-by: Lev Nachmanson --- src/util/lp/int_solver.cpp | 134 ++++++++++++++++++++++--------------- src/util/lp/int_solver.h | 4 ++ src/util/lp/lar_solver.cpp | 10 +-- src/util/lp/lar_solver.h | 18 +++-- 4 files changed, 104 insertions(+), 62 deletions(-) diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index 9de63a6fc..349393cc3 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -213,7 +213,82 @@ void int_solver::int_case_in_gomory_cut(const mpq & a, unsigned x_j, mpq & k, la } } -lia_move int_solver::mk_gomory_cut(lar_term& t, mpq& k, explanation & expl ) { +lia_move int_solver::report_conflict_from_gomory_cut(mpq & k) { + TRACE("empty_pol", + display_row_info(tout, + m_lar_solver->m_mpq_lar_core_solver.m_r_heading[m_gomory_cut_inf_column]);); + lp_assert(k.is_pos()); + // conflict 0 >= k where k is positive + k.neg(); // returning 0 <= -k + return lia_move::conflict; +} + +void int_solver::gomory_cut_adjust_t_and_k_for_size_gt_1( + vector> & pol, + lar_term & t, + mpq &k, + unsigned num_ints, + mpq & lcm_den) { + if (num_ints > 0) { + lcm_den = lcm(lcm_den, denominator(k)); + TRACE("gomory_cut_detail", tout << "k: " << k << " lcm_den: " << lcm_den << "\n"; + linear_combination_iterator_on_vector pi(pol); + m_lar_solver->print_linear_iterator(&pi, tout); + tout << "\nk: " << k << "\n";); + lp_assert(lcm_den.is_pos()); + if (!lcm_den.is_one()) { + // normalize coefficients of integer parameters to be integers. + for (auto & pi: pol) { + pi.first *= lcm_den; + SASSERT(!is_int(pi.second) || pi.first.is_int()); + } + k *= lcm_den; + } + TRACE("gomory_cut_detail", tout << "after *lcm_den\n"; + for (unsigned i = 0; i < pol.size(); i++) { + tout << pol[i].first << " * v" << pol[i].second << "\n"; + } + tout << "k: " << k << "\n";); + } + t.clear(); + // negate everything to return -pol <= -k + for (const auto & pi: pol) + t.add_monoid(-pi.first, pi.second); + k.neg(); +} + + +void int_solver::gomory_cut_adjust_t_and_k_for_size_1(const vector> & pol, lar_term& t, mpq &k) { + lp_assert(pol.size() == 1); + unsigned j = pol[0].second; + k /= pol[0].first; + bool is_lower = pol[0].first.is_pos(); + if (is_int(j) && !k.is_int()) { + k = is_lower?ceil(k):floor(k); + } + if (is_lower) { // returning -t <= -k which is equivalent to t >= k + k.neg(); + t.negate(); + } +} + + + +lia_move int_solver::report_gomory_cut(lar_term& t, mpq& k, mpq &lcm_den, unsigned num_ints) { + lp_assert(!t.is_empty()); + auto pol = t.coeffs_as_vector(); + if (pol.size() == 1) + gomory_cut_adjust_t_and_k_for_size_1(pol, t, k); + else + gomory_cut_adjust_t_and_k_for_size_gt_1(pol, t, k, num_ints, lcm_den); + m_lar_solver->subs_terms_for_debugging(t); // todo: remove later + return lia_move::cut; +} + + + + +lia_move int_solver::mk_gomory_cut(lar_term& t, mpq& k, explanation & expl) { lp_assert(column_is_int_inf(m_gomory_cut_inf_column)); @@ -238,59 +313,11 @@ lia_move int_solver::mk_gomory_cut(lar_term& t, mpq& k, explanation & expl ) { } } - if (t.is_empty()) { - TRACE("empty_pol", - display_row_info(tout, - m_lar_solver->m_mpq_lar_core_solver.m_r_heading[m_gomory_cut_inf_column]);); - lp_assert(k.is_pos()); - // conflict 0 >= k where k is positive - k.neg(); // returning 0 <= -k - return lia_move::conflict; - } + if (t.is_empty()) + return report_conflict_from_gomory_cut(k); - auto pol = t.coeffs_as_vector(); - if (pol.size() == 1) { - unsigned j = pol[0].second; - k /= pol[0].first; - bool is_lower = pol[0].first.is_pos(); - if (is_int(j) && !k.is_int()) { - k = is_lower?ceil(k):floor(k); - } - if (is_lower) { // returning -t <= -k which is equivalent to t >= k - k.neg(); - t.negate(); - } - } else { - if (num_ints > 0) { - lcm_den = lcm(lcm_den, denominator(k)); - TRACE("gomory_cut_detail", tout << "k: " << k << " lcm_den: " << lcm_den << "\n"; - linear_combination_iterator_on_vector pi(pol); - m_lar_solver->print_linear_iterator(&pi, tout); - tout << "\nk: " << k << "\n";); - SASSERT(lcm_den.is_pos()); - if (!lcm_den.is_one()) { - // normalize coefficients of integer parameters to be integers. - for (auto & pi: pol) { - pi.first *= lcm_den; - SASSERT(!is_int(pi.second) || pi.first.is_int()); - } - k *= lcm_den; - } - TRACE("gomory_cut_detail", tout << "after *lcm\n"; - for (unsigned i = 0; i < pol.size(); i++) { - tout << pol[i].first << " * v" << pol[i].second << "\n"; - } - tout << "k: " << k << "\n";); - t.clear(); - // negate everything to return -pol <= -k - for (const auto & pi: pol) - t.add_monoid(-pi.first, pi.second); - k.neg(); - } else { - lp_assert(false); // not sure what happens here - } - } - return lia_move::cut; + return report_gomory_cut(t, k, lcm_den, num_ints); + } void int_solver::init_check_data() { @@ -370,6 +397,7 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) { return lia_move::give_up; } + init_inf_int_set(); // todo - can we avoid this call? int j = find_inf_int_base_column(); if (j != -1) { // setup the call for gomory cut diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index 18b44dccb..53ae94ff8 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -106,6 +106,8 @@ private: void move_non_base_vars_to_bounds(); void branch_infeasible_int_var(unsigned); lia_move mk_gomory_cut(lar_term& t, mpq& k,explanation & ex); + lia_move report_conflict_from_gomory_cut(mpq & k); + lia_move report_gomory_cut(lar_term& t, mpq& k, mpq& lcm_den, unsigned num_ints); void init_check_data(); bool constrain_free_vars(linear_combination_iterator * r); lia_move proceed_with_gomory_cut(lar_term& t, mpq& k, explanation& ex); @@ -129,5 +131,7 @@ private: constraint_index column_upper_bound_constraint(unsigned j) const; constraint_index column_low_bound_constraint(unsigned j) const; void display_row_info(std::ostream & out, unsigned row_index) const; + void gomory_cut_adjust_t_and_k_for_size_1(const vector> & pol, lar_term & t, mpq &k); + void gomory_cut_adjust_t_and_k_for_size_gt_1(vector> & pol, lar_term & t, mpq &k, unsigned num_ints, mpq &lcm_den); }; } diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index 2e8631445..e8235c839 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -542,7 +542,7 @@ void lar_solver::set_low_bound_witness(var_index j, constraint_index ci) { m_columns_to_ul_pairs[j] = ul; } -void lar_solver::register_one_coeff_in_map(std::unordered_map & coeffs, const mpq & a, unsigned j) { +void lar_solver::register_monoid_in_map(std::unordered_map & coeffs, const mpq & a, unsigned j) { auto it = coeffs.find(j); if (it == coeffs.end()) { coeffs[j] = a; @@ -553,18 +553,18 @@ void lar_solver::register_one_coeff_in_map(std::unordered_map & void lar_solver::substitute_terms_in_linear_expression(const vector>& left_side_with_terms, - vector> &left_side, mpq & right_side) const { + vector> &left_side, mpq & free_coeff) const { std::unordered_map coeffs; for (auto & t : left_side_with_terms) { unsigned j = t.second; if (!is_term(j)) { - register_one_coeff_in_map(coeffs, t.first, j); + register_monoid_in_map(coeffs, t.first, j); } else { const lar_term & term = * m_terms[adjust_term_index(t.second)]; for (auto & p : term.coeffs()){ - register_one_coeff_in_map(coeffs, t.first * p.second , p.first); + register_monoid_in_map(coeffs, t.first * p.second , p.first); } - right_side += t.first * term.m_v; + free_coeff += t.first * term.m_v; } } diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index 46af1ae63..d6f55c612 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -149,8 +149,6 @@ public: lp_settings const & settings() const; void clear(); - - lar_solver(); void set_propagate_bounds_on_pivoted_rows_mode(bool v); @@ -263,7 +261,7 @@ public: void substitute_terms_in_linear_expression( const vector>& left_side_with_terms, - vector> &left_side, mpq & right_side) const; + vector> &left_side, mpq & free_coeff) const; void detect_rows_of_bound_change_column_for_nbasic_column(unsigned j); @@ -343,7 +341,7 @@ public: bool the_relations_are_of_same_type(const vector> & evidence, lconstraint_kind & the_kind_of_sum) const; static void register_in_map(std::unordered_map & coeffs, const lar_base_constraint & cn, const mpq & a); - static void register_one_coeff_in_map(std::unordered_map & coeffs, const mpq & a, unsigned j); + static void register_monoid_in_map(std::unordered_map & coeffs, const mpq & a, unsigned j); bool the_left_sides_sum_to_zero(const vector> & evidence) const; @@ -463,5 +461,17 @@ public: return m_columns_to_ul_pairs()[j].low_bound_witness(); } + void subs_terms_for_debugging(lar_term& t) { + vector> pol; + for (const auto & m : t.m_coeffs) { + pol.push_back(std::make_pair(m.second, adjust_column_index_to_term_index(m.first))); + } + mpq v = t.m_v; + + vector> pol_after_subs; + substitute_terms_in_linear_expression(pol, pol_after_subs, v); + t.clear(); + t = lar_term(pol_after_subs, v); + } }; } From 1490b7a15fc7a292d7774ce99c7874322e4f36f9 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Wed, 19 Jul 2017 22:14:05 -0700 Subject: [PATCH 152/159] a cleaner version of subs_term_columns Signed-off-by: Lev Nachmanson --- src/util/lp/int_solver.cpp | 2 +- src/util/lp/lar_solver.h | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index 349393cc3..793663bf1 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -281,7 +281,7 @@ lia_move int_solver::report_gomory_cut(lar_term& t, mpq& k, mpq &lcm_den, unsign gomory_cut_adjust_t_and_k_for_size_1(pol, t, k); else gomory_cut_adjust_t_and_k_for_size_gt_1(pol, t, k, num_ints, lcm_den); - m_lar_solver->subs_terms_for_debugging(t); // todo: remove later + m_lar_solver->subs_term_columns(t); return lia_move::cut; } diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index d6f55c612..3a48c4d79 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -461,14 +461,16 @@ public: return m_columns_to_ul_pairs()[j].low_bound_witness(); } - void subs_terms_for_debugging(lar_term& t) { - vector> pol; + void subs_term_columns(lar_term& t) { + vector > pol; for (const auto & m : t.m_coeffs) { pol.push_back(std::make_pair(m.second, adjust_column_index_to_term_index(m.first))); } + + mpq v = t.m_v; - vector> pol_after_subs; + // todo : remove the call to substitute_terms_in_linear_expression substitute_terms_in_linear_expression(pol, pol_after_subs, v); t.clear(); t = lar_term(pol_after_subs, v); From 943dc8118a3df069fb0674ca1c0b739d7f307ce7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 20 Jul 2017 13:44:47 +0100 Subject: [PATCH 153/159] Improved collect-statistics tactic --- src/tactic/core/collect_statistics_tactic.cpp | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/tactic/core/collect_statistics_tactic.cpp b/src/tactic/core/collect_statistics_tactic.cpp index 8e8879fef..3b820de7a 100644 --- a/src/tactic/core/collect_statistics_tactic.cpp +++ b/src/tactic/core/collect_statistics_tactic.cpp @@ -47,10 +47,10 @@ class collect_statistics_tactic : public tactic { public: collect_statistics_tactic(ast_manager & m, params_ref const & p) : - m(m), + m(m), m_params(p) { - } - + } + virtual ~collect_statistics_tactic() {} virtual tactic * translate(ast_manager & m_) { @@ -60,21 +60,21 @@ public: virtual void updt_params(params_ref const & p) { m_params = p; } - + virtual void collect_param_descrs(param_descrs & r) {} virtual void operator()(goal_ref const & g, goal_ref_buffer & result, - model_converter_ref & mc, proof_converter_ref & pc, + model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { mc = 0; - tactic_report report("collect-statistics", *g); - + tactic_report report("collect-statistics", *g); + collect_proc cp(m, m_stats); - expr_mark visited; + expr_mark visited; const unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) for_each_expr(cp, visited, g->form(i)); - + std::cout << "(" << std::endl; stats_type::iterator it = m_stats.begin(); stats_type::iterator end = m_stats.end(); @@ -84,7 +84,7 @@ public: g->inc_depth(); result.push_back(g.get()); - } + } virtual void cleanup() {} @@ -98,11 +98,12 @@ protected: class collect_proc { public: ast_manager & m; - stats_type & m_stats; + stats_type & m_stats; obj_hashtable m_seen_sorts; obj_hashtable m_seen_func_decls; + unsigned m_qdepth; - collect_proc(ast_manager & m, stats_type & s) : m(m), m_stats(s) {} + collect_proc(ast_manager & m, stats_type & s) : m(m), m_stats(s), m_qdepth(0) {} void operator()(var * v) { m_stats["bound-variables"]++; @@ -113,7 +114,18 @@ protected: m_stats["quantifiers"]++; SASSERT(is_app(q->get_expr())); app * body = to_app(q->get_expr()); + if (q->is_forall()) + m_stats["forall-variables"] += q->get_num_decls(); + else + m_stats["exists-variables"] += q->get_num_decls(); + m_stats["patterns"] += q->get_num_patterns(); + m_stats["no-patterns"] += q->get_num_no_patterns(); + m_qdepth++; + if (m_stats.find("max-quantification-depth") == m_stats.end() || + m_stats["max-quantification-depth"] < m_qdepth) + m_stats["max-quantification-depth"] = m_qdepth; this->operator()(body); + m_qdepth--; } void operator()(app * n) { @@ -121,7 +133,7 @@ protected: this->operator()(n->get_decl()); } - void operator()(sort * s) { + void operator()(sort * s) { if (m.is_uninterp(s)) { if (!m_seen_sorts.contains(s)) { m_stats["uninterpreted-sorts"]++; @@ -135,7 +147,7 @@ protected: std::stringstream ss; ss << "(declare-sort " << mk_ismt2_pp(s, m, prms) << ")"; m_stats[ss.str()]++; - + if (s->get_info()->get_num_parameters() > 0) { std::stringstream ssname; ssname << "(declare-sort (_ " << s->get_name() << " *))"; From 04824e737284670b424c84b978b0db6eee732dc6 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 20 Jul 2017 18:12:16 -0700 Subject: [PATCH 154/159] add a check in gomory cut Signed-off-by: Lev Nachmanson --- src/util/lp/int_solver.cpp | 7 +++++++ src/util/lp/int_solver.h | 1 + src/util/lp/lar_solver.h | 2 -- src/util/lp/lar_term.h | 10 ++++++++++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index 793663bf1..7753dd600 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -273,6 +273,12 @@ void int_solver::gomory_cut_adjust_t_and_k_for_size_1(const vectorm_mpq_lar_core_solver.m_r_x; + impq v = t.apply(x); + TRACE("gomory_cut", tout << "v = " << v << " k = " << k << std::endl;); + return v > k; +} lia_move int_solver::report_gomory_cut(lar_term& t, mpq& k, mpq &lcm_den, unsigned num_ints) { lp_assert(!t.is_empty()); @@ -282,6 +288,7 @@ lia_move int_solver::report_gomory_cut(lar_term& t, mpq& k, mpq &lcm_den, unsign else gomory_cut_adjust_t_and_k_for_size_gt_1(pol, t, k, num_ints, lcm_den); m_lar_solver->subs_term_columns(t); + lp_assert(current_solution_is_inf_on_cut(t, k)); return lia_move::cut; } diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index 53ae94ff8..b5a7e74f5 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -133,5 +133,6 @@ private: void display_row_info(std::ostream & out, unsigned row_index) const; void gomory_cut_adjust_t_and_k_for_size_1(const vector> & pol, lar_term & t, mpq &k); void gomory_cut_adjust_t_and_k_for_size_gt_1(vector> & pol, lar_term & t, mpq &k, unsigned num_ints, mpq &lcm_den); + bool current_solution_is_inf_on_cut(const lar_term& t, const mpq& k) const; }; } diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index 3a48c4d79..31a33d9d3 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -466,8 +466,6 @@ public: for (const auto & m : t.m_coeffs) { pol.push_back(std::make_pair(m.second, adjust_column_index_to_term_index(m.first))); } - - mpq v = t.m_v; vector> pol_after_subs; // todo : remove the call to substitute_terms_in_linear_expression diff --git a/src/util/lp/lar_term.h b/src/util/lp/lar_term.h index dc3921767..10e58dafa 100644 --- a/src/util/lp/lar_term.h +++ b/src/util/lp/lar_term.h @@ -70,6 +70,16 @@ struct lar_term { t.second.neg(); } + template + T apply(const vector& x) const { + T ret = T(m_v); + for (const auto & t : m_coeffs) { + ret += t.second * x[t.first]; + } + return ret; + } + + void clear() { m_coeffs.clear(); m_v = zero_of_type(); From 64e542bd70e0254a4a24648ca8ad96421445ad66 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Thu, 20 Jul 2017 19:13:13 -0700 Subject: [PATCH 155/159] fix term indices for the time being when exiting from check() Signed-off-by: Lev Nachmanson --- src/smt/theory_arith_int.h | 2 +- src/util/lp/int_solver.cpp | 17 ++++++++++++----- src/util/lp/lar_solver.h | 2 +- src/util/lp/lp_settings.h | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/smt/theory_arith_int.h b/src/smt/theory_arith_int.h index 7be5650c6..ca3a485c6 100644 --- a/src/smt/theory_arith_int.h +++ b/src/smt/theory_arith_int.h @@ -1387,7 +1387,7 @@ namespace smt { m_branch_cut_counter++; // TODO: add giveup code - if (true || m_branch_cut_counter % m_params.m_arith_branch_cut_ratio == 0) { // remove true :todo + if (m_branch_cut_counter % m_params.m_arith_branch_cut_ratio == 0) { TRACE("opt_verbose", display(tout);); move_non_base_vars_to_bounds(); if (!make_feasible()) { diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index 7753dd600..f40fbfb42 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -287,8 +287,6 @@ lia_move int_solver::report_gomory_cut(lar_term& t, mpq& k, mpq &lcm_den, unsign gomory_cut_adjust_t_and_k_for_size_1(pol, t, k); else gomory_cut_adjust_t_and_k_for_size_gt_1(pol, t, k, num_ints, lcm_den); - m_lar_solver->subs_term_columns(t); - lp_assert(current_solution_is_inf_on_cut(t, k)); return lia_move::cut; } @@ -323,7 +321,12 @@ lia_move int_solver::mk_gomory_cut(lar_term& t, mpq& k, explanation & expl) { if (t.is_empty()) return report_conflict_from_gomory_cut(k); - return report_gomory_cut(t, k, lcm_den, num_ints); + auto ret = report_gomory_cut(t, k, lcm_den, num_ints); + + // remove this call later :todo + m_lar_solver->subs_term_columns(t); + lp_assert(current_solution_is_inf_on_cut(t, k)); + return ret; } @@ -398,7 +401,7 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { return lia_move::ok; - if (true || (++m_branch_cut_counter) % settings().m_int_branch_cut_threshold == 0) { + if ((++m_branch_cut_counter) % settings().m_int_branch_cut_threshold == 0) { move_non_base_vars_to_bounds(); lp_status st = m_lar_solver->find_feasible_solution(); if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) { @@ -421,15 +424,19 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { TRACE("arith_int", tout << "j" << j << " does not have an integer assignment: " << get_value(j) << "\n";); lp_assert(t.is_empty()); - t.add_monoid(1, j); + t.add_monoid(mpq(1), j); k = floor(get_value(j)); TRACE("arith_int", tout << "branching v" << j << " = " << get_value(j) << "\n"; display_column(tout, j); tout << "k = " << k << std::endl; ); + // todo: remove this call later when theory_lra handles term indices + m_lar_solver->subs_term_columns(t); + lp_assert(current_solution_is_inf_on_cut(t, k)); return lia_move::branch; } } + lp_assert(m_lar_solver->m_mpq_lar_core_solver.r_basis_is_OK()); // return true; return lia_move::give_up; diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index 31a33d9d3..8189fb4b8 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -468,7 +468,7 @@ public: } mpq v = t.m_v; vector> pol_after_subs; - // todo : remove the call to substitute_terms_in_linear_expression + // todo : remove the call to substitute_terms_in_linear_expression, when theory_lra handles the terms indices substitute_terms_in_linear_expression(pol, pol_after_subs, v); t.clear(); t = lar_term(pol_after_subs, v); diff --git a/src/util/lp/lp_settings.h b/src/util/lp/lp_settings.h index 3530a13f5..d5c3b5f0e 100644 --- a/src/util/lp/lp_settings.h +++ b/src/util/lp/lp_settings.h @@ -205,7 +205,7 @@ public: max_row_length_for_bound_propagation(300), backup_costs(true), column_number_threshold_for_using_lu_in_lar_solver(4000), - m_int_branch_cut_threshold(10000000) + m_int_branch_cut_threshold(100) {} void set_resource_limit(lp_resource_limit& lim) { m_resource_limit = &lim; } From faa19117e40fa6850318fa777f884e65a68aae1a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 21 Jul 2017 17:42:48 +0100 Subject: [PATCH 156/159] Fixed inconsistent state upon solver interruption. Partially fixes #951. --- src/smt/cached_var_subst.cpp | 25 ++++++++++++++++--------- src/smt/qi_queue.cpp | 36 ++++++++++++++++++------------------ src/smt/smt_quantifier.cpp | 4 ++-- src/smt/smt_quantifier.h | 4 ++-- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/smt/cached_var_subst.cpp b/src/smt/cached_var_subst.cpp index 1db3aa0a6..c36eb6dd2 100644 --- a/src/smt/cached_var_subst.cpp +++ b/src/smt/cached_var_subst.cpp @@ -23,7 +23,7 @@ bool cached_var_subst::key_eq_proc::operator()(cached_var_subst::key * k1, cache return false; if (k1->m_num_bindings != k2->m_num_bindings) return false; - for (unsigned i = 0; i < k1->m_num_bindings; i++) + for (unsigned i = 0; i < k1->m_num_bindings; i++) if (k1->m_bindings[i] != k2->m_bindings[i]) return false; return true; @@ -49,9 +49,9 @@ void cached_var_subst::operator()(quantifier * qa, unsigned num_bindings, smt::e new_key->m_qa = qa; new_key->m_num_bindings = num_bindings; - for (unsigned i = 0; i < num_bindings; i++) + for (unsigned i = 0; i < num_bindings; i++) new_key->m_bindings[i] = bindings[i]->get_owner(); - + instances::entry * entry = m_instances.insert_if_not_there2(new_key, 0); if (entry->get_data().m_key != new_key) { SASSERT(entry->get_data().m_value != 0); @@ -60,20 +60,27 @@ void cached_var_subst::operator()(quantifier * qa, unsigned num_bindings, smt::e result = entry->get_data().m_value; return; } - - m_proc(qa->get_expr(), new_key->m_num_bindings, new_key->m_bindings, result); + + SASSERT(entry->get_data().m_value == 0); + try { + m_proc(qa->get_expr(), new_key->m_num_bindings, new_key->m_bindings, result); + } + catch (...) { + // CMW: The var_subst reducer was interrupted and m_instances is + // in an inconsistent state; we need to remove (new_key, 0). + m_instances.remove(new_key); + throw; // Throw on to smt::qi_queue/smt::solver. + } + // cache result entry->get_data().m_value = result; // remove key from cache m_new_keys[num_bindings] = 0; - + // increment reference counters m_refs.push_back(qa); for (unsigned i = 0; i < new_key->m_num_bindings; i++) m_refs.push_back(new_key->m_bindings[i]); m_refs.push_back(result); } - - - diff --git a/src/smt/qi_queue.cpp b/src/smt/qi_queue.cpp index 530d0ec88..70a3041d2 100644 --- a/src/smt/qi_queue.cpp +++ b/src/smt/qi_queue.cpp @@ -41,7 +41,7 @@ namespace smt { init_parser_vars(); m_vals.resize(15, 0.0f); } - + qi_queue::~qi_queue() { } @@ -50,7 +50,7 @@ namespace smt { if (!m_parser.parse_string(m_params.m_qi_cost.c_str(), m_cost_function)) { // it is not reasonable to abort here during the creation of smt::context just because an invalid option was provided. // throw default_exception("invalid cost function %s", m_params.m_qi_cost.c_str()); - + // using warning message instead warning_msg("invalid cost function '%s', switching to default one", m_params.m_qi_cost.c_str()); // Trying again with default function @@ -107,7 +107,7 @@ namespace smt { m_vals[SIZE] = static_cast(stat->get_size()); m_vals[DEPTH] = static_cast(stat->get_depth()); m_vals[GENERATION] = static_cast(generation); - m_vals[QUANT_GENERATION] = static_cast(stat->get_generation()); + m_vals[QUANT_GENERATION] = static_cast(stat->get_generation()); m_vals[WEIGHT] = static_cast(q->get_weight()); m_vals[VARS] = static_cast(q->get_num_decls()); m_vals[PATTERN_WIDTH] = pat ? static_cast(pat->get_num_args()) : 1.0f; @@ -118,7 +118,7 @@ namespace smt { TRACE("qi_queue_detail", for (unsigned i = 0; i < m_vals.size(); i++) { tout << m_vals[i] << " "; } tout << "\n";); return stat; } - + float qi_queue::get_cost(quantifier * q, app * pat, unsigned generation, unsigned min_top_generation, unsigned max_top_generation) { quantifier_stat * stat = set_values(q, pat, generation, min_top_generation, max_top_generation, 0); float r = m_evaluator(m_cost_function, m_vals.size(), m_vals.c_ptr()); @@ -132,11 +132,11 @@ namespace smt { float r = m_evaluator(m_new_gen_function, m_vals.size(), m_vals.c_ptr()); return static_cast(r); } - + void qi_queue::insert(fingerprint * f, app * pat, unsigned generation, unsigned min_top_generation, unsigned max_top_generation) { quantifier * q = static_cast(f->get_data()); float cost = get_cost(q, pat, generation, min_top_generation, max_top_generation); - TRACE("qi_queue_detail", + TRACE("qi_queue_detail", tout << "new instance of " << q->get_qid() << ", weight " << q->get_weight() << ", generation: " << generation << ", scope_level: " << m_context.get_scope_level() << ", cost: " << cost << "\n"; for (unsigned i = 0; i < f->get_num_args(); i++) { @@ -157,7 +157,7 @@ namespace smt { quantifier * qa = static_cast(f->get_data()); if (curr.m_cost <= m_eager_cost_threshold) { - instantiate(curr); + instantiate(curr); } else if (m_params.m_qi_promote_unsat && m_checker.is_unsat(qa->get_expr(), f->get_num_args(), f->get_args())) { // do not delay instances that produce a conflict. @@ -193,7 +193,7 @@ namespace smt { // This nasty side-effect may change the behavior of Z3. m_manager.trace_stream() << " #" << bindings[i]->get_owner_id(); } - + #endif if (m_manager.proofs_enabled()) m_manager.trace_stream() << " #" << proof_id; @@ -233,7 +233,7 @@ namespace smt { if (m_manager.is_true(s_instance)) { TRACE("checker", tout << "reduced to true, before:\n" << mk_ll_pp(instance, m_manager);); - if (m_manager.has_trace_stream()) + if (m_manager.has_trace_stream()) m_manager.trace_stream() << "[end-of-instance]\n"; return; @@ -278,7 +278,7 @@ namespace smt { pr1 = m_manager.mk_modus_ponens(qi_pr, rw); } else { - app * bare_s_lemma = m_manager.mk_or(m_manager.mk_not(q), s_instance); + app * bare_s_lemma = m_manager.mk_or(m_manager.mk_not(q), s_instance); proof * prs[1] = { pr.get() }; proof * cg = m_manager.mk_congruence(bare_lemma, bare_s_lemma, 1, prs); proof * rw = m_manager.mk_rewrite(bare_s_lemma, lemma); @@ -331,13 +331,13 @@ namespace smt { s.m_instances_lim = m_instances.size(); s.m_instantiated_trail_lim = m_instantiated_trail.size(); } - + void qi_queue::pop_scope(unsigned num_scopes) { unsigned new_lvl = m_scopes.size() - num_scopes; scope & s = m_scopes[new_lvl]; unsigned old_sz = s.m_instantiated_trail_lim; unsigned sz = m_instantiated_trail.size(); - for (unsigned i = old_sz; i < sz; i++) + for (unsigned i = old_sz; i < sz; i++) m_delayed_entries[m_instantiated_trail[i]].m_instantiated = false; m_instantiated_trail.shrink(old_sz); m_delayed_entries.shrink(s.m_delayed_entries_lim); @@ -359,7 +359,7 @@ namespace smt { } bool qi_queue::final_check_eh() { - TRACE("qi_queue", display_delayed_instances_stats(tout); tout << "lazy threshold: " << m_params.m_qi_lazy_threshold + TRACE("qi_queue", display_delayed_instances_stats(tout); tout << "lazy threshold: " << m_params.m_qi_lazy_threshold << ", scope_level: " << m_context.get_scope_level() << "\n";); if (m_params.m_qi_conservative_final_check) { bool init = false; @@ -379,7 +379,7 @@ namespace smt { entry & e = m_delayed_entries[i]; TRACE("qi_queue", tout << e.m_qb << ", cost: " << e.m_cost << ", instantiated: " << e.m_instantiated << "\n";); if (!e.m_instantiated && e.m_cost <= min_cost) { - TRACE("qi_queue", + TRACE("qi_queue", tout << "lazy quantifier instantiation...\n" << mk_pp(static_cast(e.m_qb->get_data()), m_manager) << "\ncost: " << e.m_cost << "\n";); result = false; m_instantiated_trail.push_back(i); @@ -389,13 +389,13 @@ namespace smt { } return result; } - + bool result = true; for (unsigned i = 0; i < m_delayed_entries.size(); i++) { entry & e = m_delayed_entries[i]; TRACE("qi_queue", tout << e.m_qb << ", cost: " << e.m_cost << ", instantiated: " << e.m_instantiated << "\n";); if (!e.m_instantiated && e.m_cost <= m_params.m_qi_lazy_threshold) { - TRACE("qi_queue", + TRACE("qi_queue", tout << "lazy quantifier instantiation...\n" << mk_pp(static_cast(e.m_qb->get_data()), m_manager) << "\ncost: " << e.m_cost << "\n";); result = false; m_instantiated_trail.push_back(i); @@ -443,7 +443,7 @@ namespace smt { quantifier * qa = *it2; delayed_qa_info info; qa2info.find(qa, info); - out << qa->get_qid() << ": " << info.m_num << " [" << info.m_min_cost << ", " << info.m_max_cost << "]\n"; + out << qa->get_qid() << ": " << info.m_num << " [" << info.m_min_cost << ", " << info.m_max_cost << "]\n"; } } @@ -482,6 +482,6 @@ namespace smt { } #endif } - + }; diff --git a/src/smt/smt_quantifier.cpp b/src/smt/smt_quantifier.cpp index 10e2df988..1c8f94edf 100644 --- a/src/smt/smt_quantifier.cpp +++ b/src/smt/smt_quantifier.cpp @@ -135,7 +135,7 @@ namespace smt { m_qi_queue.insert(f, pat, max_generation, min_top_generation, max_top_generation); // TODO m_num_instances++; } - TRACE("quantifier", + TRACE("quantifier", tout << mk_pp(q, m()) << " "; for (unsigned i = 0; i < num_bindings; ++i) { tout << mk_pp(bindings[i]->get_owner(), m()) << " "; @@ -372,7 +372,7 @@ namespace smt { quantifier_manager_plugin * plugin = m_imp->m_plugin->mk_fresh(); m_imp->~imp(); m_imp = new (m_imp) imp(*this, ctx, p, plugin); - plugin->set_manager(*this); + plugin->set_manager(*this); } void quantifier_manager::display(std::ostream & out) const { diff --git a/src/smt/smt_quantifier.h b/src/smt/smt_quantifier.h index 6dcf20583..96af9909a 100644 --- a/src/smt/smt_quantifier.h +++ b/src/smt/smt_quantifier.h @@ -75,7 +75,7 @@ namespace smt { }; bool model_based() const; - bool mbqi_enabled(quantifier *q) const; // can mbqi instantiate this quantifier? + bool mbqi_enabled(quantifier *q) const; // can mbqi instantiate this quantifier? void adjust_model(proto_model * m); check_model_result check_model(proto_model * m, obj_map const & root2value); @@ -167,7 +167,7 @@ namespace smt { virtual void push() = 0; virtual void pop(unsigned num_scopes) = 0; - + }; }; From 0f1583309d0813e87d6003fe46cf8bb32899d773 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 21 Jul 2017 21:12:45 +0100 Subject: [PATCH 157/159] Bugfix for fp.fma. One piece of puzzle #872. --- src/ast/fpa/fpa2bv_converter.cpp | 35 ++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 2c0ba1ce1..99b8c5ac8 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1632,8 +1632,6 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, res_exp = e_exp; - // Result could overflow into 4.xxx ... - family_id bvfid = m_bv_util.get_fid(); expr_ref res_sgn_c1(m), res_sgn_c2(m), res_sgn_c3(m); expr_ref not_e_sgn(m), not_f_sgn(m), not_sign_bv(m); @@ -1646,11 +1644,34 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, expr * res_sgn_or_args[3] = { res_sgn_c1, res_sgn_c2, res_sgn_c3 }; res_sgn = m_bv_util.mk_bv_or(3, res_sgn_or_args); + // Result could have overflown into 4.xxx. + SASSERT(m_bv_util.get_bv_size(sig_abs) == 2 * sbits + 2); + expr_ref ovfl_into_4(m); + ovfl_into_4 = m.mk_eq(m_bv_util.mk_extract(2 * sbits + 1, 2 * sbits, sig_abs), + m_bv_util.mk_numeral(1, 2)); + dbg_decouple("fpa2bv_fma_ovfl_into_4", ovfl_into_4); if (sbits > 5) { - sticky_raw = m_bv_util.mk_extract(sbits - 5, 0, sig_abs); - sticky = m_bv_util.mk_zero_extend(sbits + 3, m.mk_app(bvfid, OP_BREDOR, sticky_raw.get())); - expr * res_or_args[2] = { m_bv_util.mk_extract(2 * sbits - 1, sbits - 4, sig_abs), sticky }; - res_sig = m_bv_util.mk_bv_or(2, res_or_args); + expr_ref sticky_raw(m), sig_upper(m), sticky_redd(m), res_sig_norm(m); + sticky_raw = m_bv_util.mk_extract(sbits - 4, 0, sig_abs); + sig_upper = m_bv_util.mk_extract(2 * sbits, sbits - 3, sig_abs); + SASSERT(m_bv_util.get_bv_size(sig_upper) == sbits + 4); + sticky_redd = m.mk_app(bvfid, OP_BREDOR, sticky_raw.get()); + sticky = m_bv_util.mk_zero_extend(sbits + 3, sticky_redd); + expr * res_or_args[2] = { sig_upper, sticky }; + res_sig_norm = m_bv_util.mk_bv_or(2, res_or_args); + + expr_ref sticky_raw_ovfl(m), sig_upper_ovfl(m), sticky_redd_ovfl(m), sticky_ovfl(m), res_sig_ovfl(m); + sticky_raw_ovfl = m_bv_util.mk_extract(sbits - 4, 0, sig_abs); + sig_upper_ovfl = m_bv_util.mk_extract(2 * sbits, sbits - 3, sig_abs); + SASSERT(m_bv_util.get_bv_size(sig_upper_ovfl) == sbits + 4); + sticky_redd_ovfl = m.mk_app(bvfid, OP_BREDOR, sticky_raw_ovfl.get()); + sticky_ovfl = m_bv_util.mk_zero_extend(sbits + 3, sticky_redd_ovfl); + expr * res_or_args_ovfl[2] = { sig_upper_ovfl, sticky_ovfl }; + res_sig_ovfl = m_bv_util.mk_bv_or(2, res_or_args_ovfl); + + res_sig = m.mk_ite(ovfl_into_4, res_sig_ovfl, res_sig_norm); + res_exp = m.mk_ite(ovfl_into_4, m_bv_util.mk_bv_add(res_exp, m_bv_util.mk_numeral(1, ebits+2)), + res_exp); } else { unsigned too_short = 6 - sbits; @@ -1658,6 +1679,8 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, res_sig = m_bv_util.mk_extract(sbits + 3, 0, sig_abs); } dbg_decouple("fpa2bv_fma_add_sum_sticky", sticky); + dbg_decouple("fpa2bv_fma_sig_abs", sig_abs); + dbg_decouple("fpa2bv_fma_res_sig", res_sig); SASSERT(m_bv_util.get_bv_size(res_sig) == sbits + 4); expr_ref is_zero_sig(m), nil_sbits4(m); From bd4fb22665bd7d2d4843080c7a425044394cda68 Mon Sep 17 00:00:00 2001 From: Lev Nachmanson Date: Fri, 21 Jul 2017 21:09:51 -0700 Subject: [PATCH 158/159] track the set of integer variables that are not set to integer values Signed-off-by: Lev Nachmanson --- src/util/lp/int_solver.cpp | 38 +++++++++---------- src/util/lp/int_solver.h | 5 ++- src/util/lp/lar_solver.cpp | 23 ++++++++++- src/util/lp/lar_solver.h | 5 ++- src/util/lp/lp_core_solver_base.h | 14 ++++++- src/util/lp/lp_core_solver_base.hpp | 3 +- src/util/lp/lp_primal_core_solver.h | 2 +- src/util/lp/lp_primal_core_solver.hpp | 4 +- src/util/lp/lp_primal_core_solver_tableau.hpp | 4 +- 9 files changed, 66 insertions(+), 32 deletions(-) diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp index f40fbfb42..90dfef767 100644 --- a/src/util/lp/int_solver.cpp +++ b/src/util/lp/int_solver.cpp @@ -21,7 +21,6 @@ void int_solver::fix_non_base_columns() { return; if (m_lar_solver->find_feasible_solution() == lp_status::INFEASIBLE) failed(); - init_inf_int_set(); lp_assert(is_feasible() && inf_int_set_is_correct()); } @@ -61,14 +60,22 @@ void int_solver::trace_inf_rows() const { ); } +int_set& int_solver::inf_int_set() { + return m_lar_solver->m_inf_int_set; +} + +const int_set& int_solver::inf_int_set() const { + return m_lar_solver->m_inf_int_set; +} + int int_solver::find_inf_int_base_column() { - if (m_inf_int_set.is_empty()) + if (inf_int_set().is_empty()) return -1; int j = find_inf_int_boxed_base_column_with_smallest_range(); if (j != -1) return j; - unsigned k = settings().random_next() % m_inf_int_set.m_index.size(); - return m_inf_int_set.m_index[k]; + unsigned k = settings().random_next() % inf_int_set().m_index.size(); + return inf_int_set().m_index[k]; } int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { @@ -79,7 +86,7 @@ int int_solver::find_inf_int_boxed_base_column_with_smallest_range() { unsigned n = 0; lar_core_solver & lcs = m_lar_solver->m_mpq_lar_core_solver; - for (int j : m_inf_int_set.m_index) { + for (int j : inf_int_set().m_index) { lp_assert(is_base(j) && column_is_int_inf(j)); if (!is_boxed(j)) continue; @@ -331,7 +338,6 @@ lia_move int_solver::mk_gomory_cut(lar_term& t, mpq& k, explanation & expl) { } void int_solver::init_check_data() { - init_inf_int_set(); unsigned n = m_lar_solver->A_r().column_count(); m_old_values_set.resize(n); m_old_values_data.resize(n); @@ -402,12 +408,13 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) { if ((++m_branch_cut_counter) % settings().m_int_branch_cut_threshold == 0) { - move_non_base_vars_to_bounds(); + move_non_base_vars_to_bounds(); // todo track changed variables lp_status st = m_lar_solver->find_feasible_solution(); if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) { return lia_move::give_up; } - init_inf_int_set(); // todo - can we avoid this call? + lp_assert(inf_int_set_is_correct()); + // init_inf_int_set(); // todo - can we avoid this call? int j = find_inf_int_base_column(); if (j != -1) { // setup the call for gomory cut @@ -862,7 +869,7 @@ void int_solver::display_column(std::ostream & out, unsigned j) const { bool int_solver::inf_int_set_is_correct() const { for (unsigned j = 0; j < m_lar_solver->A_r().column_count(); j++) { - if (m_inf_int_set.contains(j) != (is_int(j) && (!value_is_int(j)))) + if (inf_int_set().contains(j) != (is_int(j) && (!value_is_int(j)))) return false; } return true; @@ -872,20 +879,11 @@ bool int_solver::column_is_int_inf(unsigned j) const { return is_int(j) && (!value_is_int(j)); } -void int_solver::init_inf_int_set() { - m_inf_int_set.clear(); - m_inf_int_set.resize(m_lar_solver->A_r().column_count()); - for (unsigned j = 0; j < m_lar_solver->A_r().column_count(); j++) { - if (column_is_int_inf(j)) - m_inf_int_set.insert(j); - } -} - void int_solver::update_column_in_int_inf_set(unsigned j) { if (is_int(j) && (!value_is_int(j))) - m_inf_int_set.insert(j); + inf_int_set().insert(j); else - m_inf_int_set.erase(j); + inf_int_set().erase(j); } bool int_solver::is_base(unsigned j) const { diff --git a/src/util/lp/int_solver.h b/src/util/lp/int_solver.h index b5a7e74f5..104e9b321 100644 --- a/src/util/lp/int_solver.h +++ b/src/util/lp/int_solver.h @@ -34,13 +34,15 @@ public: lar_solver *m_lar_solver; int_set m_old_values_set; vector m_old_values_data; - int_set m_inf_int_set; unsigned m_branch_cut_counter; linear_combination_iterator* m_iter_on_gomory_row; unsigned m_gomory_cut_inf_column; bool m_found_free_var_in_gomory_row; + // methods int_solver(lar_solver* lp); + int_set& inf_int_set(); + const int_set& inf_int_set() const; // main function to check that solution provided by lar_solver is valid for integral values, // or provide a way of how it can be adjusted. lia_move check(lar_term& t, mpq& k, explanation& ex); @@ -96,7 +98,6 @@ private: const impq & get_value(unsigned j) const; void display_column(std::ostream & out, unsigned j) const; bool inf_int_set_is_correct() const; - void init_inf_int_set(); void update_column_in_int_inf_set(unsigned j); bool column_is_int_inf(unsigned j) const; void trace_inf_rows() const; diff --git a/src/util/lp/lar_solver.cpp b/src/util/lp/lar_solver.cpp index e8235c839..e7ef4f748 100644 --- a/src/util/lp/lar_solver.cpp +++ b/src/util/lp/lar_solver.cpp @@ -30,7 +30,17 @@ void clear() {lp_assert(false); // not implemented lar_solver::lar_solver() : m_status(lp_status::OPTIMAL), m_infeasible_column_index(-1), m_terms_start_index(1000000), - m_mpq_lar_core_solver(m_settings, *this) + m_mpq_lar_core_solver(m_settings, *this), + m_tracker_of_x_change([&](unsigned j, const impq & x){ + if (!var_is_int(j)) { + lp_assert(m_inf_int_set.contains(j) == false); + return; + } + if (m_mpq_lar_core_solver.m_r_x[j].is_int()) + m_inf_int_set.erase(j); + else + m_inf_int_set.insert(j); + }) { } @@ -279,6 +289,10 @@ lp_status lar_solver::get_status() const { return m_status;} void lar_solver::set_status(lp_status s) {m_status = s;} +bool lar_solver::has_int_var() const { + return m_mpq_lar_core_solver.m_r_solver.m_tracker_of_x_change != nullptr; +} + lp_status lar_solver::find_feasible_solution() { m_settings.st().m_make_feasible++; if (A_r().column_count() > m_settings.st().m_max_cols) @@ -288,6 +302,10 @@ lp_status lar_solver::find_feasible_solution() { if (strategy_is_undecided()) decide_on_strategy_and_adjust_initial_state(); + if (has_int_var()) { + m_inf_int_set.resize(A_r().column_count()); + } + m_mpq_lar_core_solver.m_r_solver.m_look_for_feasible_solution_only = true; return solve(); } @@ -1474,6 +1492,9 @@ var_index lar_solver::add_var(unsigned ext_j, bool is_int) { m_columns_to_ul_pairs.push_back(ul_pair(static_cast(-1))); add_non_basic_var_to_core_fields(ext_j, is_int); lp_assert(sizes_are_correct()); + if (is_int) { + m_mpq_lar_core_solver.m_r_solver.set_tracker_of_x(& m_tracker_of_x_change); + } return i; } diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h index 8189fb4b8..df4df5ca1 100644 --- a/src/util/lp/lar_solver.h +++ b/src/util/lp/lar_solver.h @@ -68,7 +68,8 @@ public: lar_core_solver m_mpq_lar_core_solver; unsigned constraint_count() const; const lar_base_constraint& get_constraint(unsigned ci) const; - + std::function m_tracker_of_x_change; + int_set m_inf_int_set; ////////////////// methods //////////////////////////////// static_matrix> & A_r(); static_matrix> const & A_r() const; @@ -473,5 +474,7 @@ public: t.clear(); t = lar_term(pol_after_subs, v); } + + bool has_int_var() const; }; } diff --git a/src/util/lp/lp_core_solver_base.h b/src/util/lp/lp_core_solver_base.h index 12c93ec93..0a07055a4 100644 --- a/src/util/lp/lp_core_solver_base.h +++ b/src/util/lp/lp_core_solver_base.h @@ -69,6 +69,12 @@ public: bool m_tracing_basis_changes; int_set* m_pivoted_rows; bool m_look_for_feasible_solution_only; + std::function * m_tracker_of_x_change; + + void set_tracker_of_x(std::function* tracker) { + m_tracker_of_x_change = tracker; + } + void start_tracing_basis_changes() { m_trace_of_basis_change_vector.resize(0); m_tracing_basis_changes = true; @@ -670,16 +676,20 @@ public: void update_column_in_inf_set(unsigned j) { if (column_is_feasible(j)) { - m_inf_set.erase(j); + remove_column_from_inf_set(j); } else { - m_inf_set.insert(j); + insert_column_into_inf_set(j); } } void insert_column_into_inf_set(unsigned j) { + if (m_tracker_of_x_change != nullptr) + (*m_tracker_of_x_change)(j, m_x[j]); m_inf_set.insert(j); lp_assert(!column_is_feasible(j)); } void remove_column_from_inf_set(unsigned j) { + if (m_tracker_of_x_change != nullptr) + (*m_tracker_of_x_change)(j, m_x[j]); m_inf_set.erase(j); lp_assert(column_is_feasible(j)); } diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp index bd3410b45..5ac6c4c22 100644 --- a/src/util/lp/lp_core_solver_base.hpp +++ b/src/util/lp/lp_core_solver_base.hpp @@ -52,7 +52,8 @@ lp_core_solver_base(static_matrix & A, m_steepest_edge_coefficients(A.column_count()), m_tracing_basis_changes(false), m_pivoted_rows(nullptr), - m_look_for_feasible_solution_only(false) { + m_look_for_feasible_solution_only(false), + m_tracker_of_x_change(nullptr) { lp_assert(bounds_for_boxed_are_set_correctly()); init(); init_basis_heading_and_non_basic_columns_vector(); diff --git a/src/util/lp/lp_primal_core_solver.h b/src/util/lp/lp_primal_core_solver.h index 77784746a..7577516d2 100644 --- a/src/util/lp/lp_primal_core_solver.h +++ b/src/util/lp/lp_primal_core_solver.h @@ -779,7 +779,7 @@ public: if (this->m_basis_heading[j] < 0) continue; if (!this->column_is_feasible(j)) - this->m_inf_set.insert(j); + this->insert_column_into_inf_set(j); } } diff --git a/src/util/lp/lp_primal_core_solver.hpp b/src/util/lp/lp_primal_core_solver.hpp index b3d6921d9..27c92e5e0 100644 --- a/src/util/lp/lp_primal_core_solver.hpp +++ b/src/util/lp/lp_primal_core_solver.hpp @@ -1197,9 +1197,9 @@ lp_primal_core_solver::init_infeasibility_cost_for_column(unsigned j) { } if (numeric_traits::is_zero(this->m_costs[j])) { - this->m_inf_set.erase(j); + this->remove_column_from_inf_set(j); } else { - this->m_inf_set.insert(j); + this->insert_column_into_inf_set(j); } if (!this->m_settings.use_breakpoints_in_feasibility_search) { this->m_costs[j] = - this->m_costs[j]; diff --git a/src/util/lp/lp_primal_core_solver_tableau.hpp b/src/util/lp/lp_primal_core_solver_tableau.hpp index 3cacd2dbb..867c321ba 100644 --- a/src/util/lp/lp_primal_core_solver_tableau.hpp +++ b/src/util/lp/lp_primal_core_solver_tableau.hpp @@ -349,9 +349,9 @@ update_x_tableau(unsigned entering, const X& delta) { this->m_x[j] -= delta * this->m_A.get_val(c); update_inf_cost_for_column_tableau(j); if (is_zero(this->m_costs[j])) - this->m_inf_set.erase(j); + this->remove_column_from_inf_set(j); else - this->m_inf_set.insert(j); + this->insert_column_into_inf_set(j); } } lp_assert(this->A_mult_x_is_off() == false); From c8fe91d8c5cda754f9e560caee07f0491a1c92b4 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 24 Jul 2017 16:12:46 -0700 Subject: [PATCH 159/159] add handling for nested terms Signed-off-by: Nikolaj Bjorner --- src/smt/theory_lra.cpp | 149 ++++++++++++++++++++++++++++++----------- 1 file changed, 111 insertions(+), 38 deletions(-) diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp index 0813e1dcd..e9bb13b8e 100644 --- a/src/smt/theory_lra.cpp +++ b/src/smt/theory_lra.cpp @@ -602,8 +602,8 @@ namespace smt { } bool all_zeros(vector const& v) const { - for (unsigned i = 0; i < v.size(); ++i) { - if (!v[i].is_zero()) { + for (rational const& r : v) { + if (!r.is_zero()) { return false; } } @@ -1031,20 +1031,32 @@ namespace smt { return m_solver->var_is_registered(m_theory_var2var_index[v]); } + mutable vector> m_todo_terms; + lp::impq get_ivalue(theory_var v) const { lp_assert(can_get_ivalue(v)); lp::var_index vi = m_theory_var2var_index[v]; if (!m_solver->is_term(vi)) return m_solver->get_value(vi); - - const lp::lar_term& term = m_solver->get_term(vi); - lp::impq result(term.m_v); - for (const auto & i: term.m_coeffs) { - result += m_solver->get_value(i.first) * i.second; + m_todo_terms.push_back(std::make_pair(vi, rational::one())); + lp::impq result(0); + while (!m_todo_terms.empty()) { + vi = m_todo_terms.back().first; + rational coeff = m_todo_terms.back().second; + m_todo_terms.pop_back(); + if (m_solver->is_term(vi)) { + const lp::lar_term& term = m_solver->get_term(vi); + result += term.m_v * coeff; + for (const auto & i: term.m_coeffs) { + m_todo_terms.push_back(std::make_pair(i.first, coeff * i.second)); + } + } + else { + result += m_solver->get_value(vi) * coeff; + } } return result; } - rational get_value(theory_var v) const { if (!can_get_value(v)) return rational::zero(); @@ -1052,17 +1064,25 @@ namespace smt { if (m_variable_values.count(vi) > 0) { return m_variable_values[vi]; } - if (m_solver->is_term(vi)) { - const lp::lar_term& term = m_solver->get_term(vi); - rational result = term.m_v; - for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { - result += m_variable_values[i->first] * i->second; + m_todo_terms.push_back(std::make_pair(vi, rational::one())); + rational result(0); + while (!m_todo_terms.empty()) { + lp::var_index wi = m_todo_terms.back().first; + rational coeff = m_todo_terms.back().second; + m_todo_terms.pop_back(); + if (m_solver->is_term(wi)) { + const lp::lar_term& term = m_solver->get_term(wi); + result += term.m_v * coeff; + for (auto const& i : term.m_coeffs) { + m_todo_terms.push_back(std::make_pair(i.first, i.second * coeff)); + } + } + else { + result += m_variable_values[wi] * coeff; } - m_variable_values[vi] = result; - return result; } - UNREACHABLE(); - return m_variable_values[vi]; + m_variable_values[vi] = result; + return result; } void init_variable_values() { @@ -1550,8 +1570,8 @@ namespace smt { SASSERT(validate_assign(lit)); if (m_core.size() < small_lemma_size() && m_eqs.empty()) { m_core2.reset(); - for (unsigned i = 0; i < m_core.size(); ++i) { - m_core2.push_back(~m_core[i]); + for (auto const& c : m_core) { + m_core2.push_back(~c); } m_core2.push_back(lit); justification * js = 0; @@ -1926,16 +1946,29 @@ namespace smt { ++m_stats.m_bounds_propagations; } + svector m_todo_vars; + void add_use_lists(lp_api::bound* b) { theory_var v = b->get_var(); lp::var_index vi = get_var_index(v); - if (m_solver->is_term(vi)) { + if (!m_solver->is_term(vi)) { + return; + } + m_todo_vars.push_back(vi); + while (!m_todo_vars.empty()) { + vi = m_todo_vars.back(); + m_todo_vars.pop_back(); lp::lar_term const& term = m_solver->get_term(vi); for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { lp::var_index wi = i->first; - unsigned w = m_var_index2theory_var[wi]; - m_use_list.reserve(w + 1, ptr_vector()); - m_use_list[w].push_back(b); + if (m_solver->is_term(wi)) { + m_todo_vars.push_back(wi); + } + else { + unsigned w = m_var_index2theory_var[wi]; + m_use_list.reserve(w + 1, ptr_vector()); + m_use_list[w].push_back(b); + } } } } @@ -1943,13 +1976,24 @@ namespace smt { void del_use_lists(lp_api::bound* b) { theory_var v = b->get_var(); lp::var_index vi = m_theory_var2var_index[v]; - if (m_solver->is_term(vi)) { + if (!m_solver->is_term(vi)) { + return; + } + m_todo_vars.push_back(vi); + while (!m_todo_vars.empty()) { + vi = m_todo_vars.back(); + m_todo_vars.pop_back(); lp::lar_term const& term = m_solver->get_term(vi); for (auto i = term.m_coeffs.begin(); i != term.m_coeffs.end(); ++i) { lp::var_index wi = i->first; - unsigned w = m_var_index2theory_var[wi]; - SASSERT(m_use_list[w].back() == b); - m_use_list[w].pop_back(); + if (m_solver->is_term(wi)) { + m_todo_vars.push_back(wi); + } + else { + unsigned w = m_var_index2theory_var[wi]; + SASSERT(m_use_list[w].back() == b); + m_use_list[w].pop_back(); + } } } } @@ -2036,6 +2080,9 @@ namespace smt { lp::constraint_index ci; rational value; bool is_strict; + if (m_solver->is_term(wi)) { + return false; + } if (coeff.second.is_neg() == is_lub) { // -3*x ... <= lub based on lower bound for x. if (!m_solver->has_lower_bound(wi, ci, value, is_strict)) { @@ -2381,15 +2428,31 @@ namespace smt { SASSERT(m_use_nra_model); lp::var_index vi = m_theory_var2var_index[v]; if (m_solver->is_term(vi)) { - lp::lar_term const& term = m_solver->get_term(vi); - scoped_anum r1(m_nra->am()); - m_nra->am().set(r, term.m_v.to_mpq()); - - for (auto const coeff : term.m_coeffs) { - lp::var_index wi = coeff.first; - m_nra->am().set(r1, coeff.second.to_mpq()); - m_nra->am().mul(m_nra->value(wi), r1, r1); - m_nra->am().add(r1, r, r); + + m_todo_terms.push_back(std::make_pair(vi, rational::one())); + + m_nra->am().set(r, 0); + while (!m_todo_terms.empty()) { + rational wcoeff = m_todo_terms.back().second; + lp::var_index wi = m_todo_terms.back().first; + m_todo_terms.pop_back(); + lp::lar_term const& term = m_solver->get_term(vi); + scoped_anum r1(m_nra->am()); + rational c1 = term.m_v * wcoeff; + m_nra->am().set(r1, c1.to_mpq()); + m_nra->am().add(r, r1, r); + for (auto const coeff : term.m_coeffs) { + lp::var_index wi = coeff.first; + c1 = coeff.second * wcoeff; + if (m_solver->is_term(wi)) { + m_todo_terms.push_back(std::make_pair(wi, c1)); + } + else { + m_nra->am().set(r1, c1.to_mpq()); + m_nra->am().mul(m_nra->value(wi), r1, r1); + m_nra->am().add(r1, r, r); + } + } } return r; } @@ -2489,10 +2552,14 @@ namespace smt { theory_lra::inf_eps maximize(theory_var v, expr_ref& blocker, bool& has_shared) { lp::var_index vi = m_theory_var2var_index.get(v, UINT_MAX); vector > coeffs; - rational coeff; + rational coeff(0); + // + // TBD: change API for maximize_term to take a proper term as input. + // if (m_solver->is_term(vi)) { const lp::lar_term& term = m_solver->get_term(vi); for (auto & ti : term.m_coeffs) { + SASSERT(!m_solver->is_term(ti.first)); coeffs.push_back(std::make_pair(ti.second, ti.first)); } coeff = term.m_v; @@ -2550,7 +2617,13 @@ namespace smt { app_ref mk_term(lp::lar_term const& term, bool is_int) { expr_ref_vector args(m); for (auto & ti : term.m_coeffs) { - theory_var w = m_var_index2theory_var[ti.first]; + theory_var w; + if (m_solver->is_term(ti.first)) { + w = m_term_index2theory_var[m_solver->adjust_term_index(ti.first)]; + } + else { + w = m_var_index2theory_var[ti.first]; + } expr* o = get_enode(w)->get_owner(); if (ti.second.is_one()) { args.push_back(o);