mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 11:42:28 +00:00 
			
		
		
		
	Merge branch 'master' into nl_branches
This commit is contained in:
		
						commit
						9aeaed8f53
					
				
					 52 changed files with 735 additions and 590 deletions
				
			
		|  | @ -479,15 +479,15 @@ bool compare_nodes(ast const * n1, ast const * n2) { | |||
|         return | ||||
|             q1->get_kind()         == q2->get_kind() && | ||||
|             q1->get_num_decls()    == q2->get_num_decls() && | ||||
|             q1->get_expr()         == q2->get_expr() && | ||||
|             q1->get_weight()       == q2->get_weight() && | ||||
|             q1->get_num_patterns() == q2->get_num_patterns() && | ||||
|             compare_arrays(q1->get_decl_sorts(), | ||||
|                            q2->get_decl_sorts(), | ||||
|                            q1->get_num_decls()) && | ||||
|             compare_arrays(q1->get_decl_names(), | ||||
|                            q2->get_decl_names(), | ||||
|                            q1->get_num_decls()) && | ||||
|             q1->get_expr()         == q2->get_expr() && | ||||
|             q1->get_weight()       == q2->get_weight() && | ||||
|             q1->get_num_patterns() == q2->get_num_patterns() && | ||||
|             ((q1->get_qid().is_numerical() && q2->get_qid().is_numerical()) || | ||||
|              (q1->get_qid() == q2->get_qid())) &&  | ||||
|             compare_arrays(q1->get_patterns(), | ||||
|  | @ -542,22 +542,6 @@ inline unsigned ast_array_hash(T * const * array, unsigned size, unsigned init_v | |||
|     } } | ||||
| } | ||||
| 
 | ||||
| unsigned get_asts_hash(unsigned sz, ast * const* ns, unsigned init) { | ||||
|     return ast_array_hash<ast>(ns, sz, init); | ||||
| } | ||||
| unsigned get_apps_hash(unsigned sz, app * const* ns, unsigned init) { | ||||
|     return ast_array_hash<app>(ns, sz, init); | ||||
| } | ||||
| unsigned get_exprs_hash(unsigned sz, expr * const* ns, unsigned init) { | ||||
|     return ast_array_hash<expr>(ns, sz, init); | ||||
| } | ||||
| unsigned get_sorts_hash(unsigned sz, sort * const* ns, unsigned init) { | ||||
|     return ast_array_hash<sort>(ns, sz, init); | ||||
| } | ||||
| unsigned get_decl_hash(unsigned sz, func_decl* const* ns, unsigned init) { | ||||
|     return ast_array_hash<func_decl>(ns, sz, init); | ||||
| } | ||||
| 
 | ||||
| unsigned get_node_hash(ast const * n) { | ||||
|     unsigned a, b, c; | ||||
| 
 | ||||
|  |  | |||
|  | @ -970,11 +970,6 @@ inline quantifier const * to_quantifier(ast const * n) { SASSERT(is_quantifier(n | |||
| unsigned get_node_hash(ast const * n); | ||||
| bool compare_nodes(ast const * n1, ast const * n2); | ||||
| unsigned get_node_size(ast const * n); | ||||
| unsigned get_asts_hash(unsigned sz, ast * const* ns, unsigned init); | ||||
| unsigned get_apps_hash(unsigned sz, app * const* ns, unsigned init); | ||||
| unsigned get_exprs_hash(unsigned sz, expr * const* ns, unsigned init); | ||||
| unsigned get_sorts_hash(unsigned sz, sort * const* ns, unsigned init); | ||||
| unsigned get_decl_hash(unsigned sz, func_decl* const* ns, unsigned init); | ||||
| 
 | ||||
| // This is the internal comparison functor for hash-consing AST nodes.
 | ||||
| struct ast_eq_proc { | ||||
|  |  | |||
|  | @ -17,8 +17,6 @@ Revision History: | |||
| 
 | ||||
| --*/ | ||||
| 
 | ||||
| #ifndef ELIM_BOUNDS_H_ | ||||
| #define ELIM_BOUNDS_H_ | ||||
| 
 | ||||
| #include "ast/used_vars.h" | ||||
| #include "util/obj_hashtable.h" | ||||
|  | @ -201,4 +199,3 @@ bool elim_bounds_cfg::reduce_quantifier(quantifier * q, | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| #endif /* ELIM_BOUNDS_H_ */ | ||||
|  |  | |||
|  | @ -37,6 +37,7 @@ class bound_simplifier : public dependent_expr_simplifier { | |||
|     unsynch_mpq_manager     nm; | ||||
|     small_object_allocator  m_alloc; | ||||
|     bound_propagator        bp; | ||||
|     u_dependency_manager    m_dep_manager; | ||||
|     dep_intervals           m_interval; | ||||
|     ptr_vector<expr>        m_var2expr; | ||||
|     unsigned_vector         m_expr2var; | ||||
|  | @ -105,7 +106,7 @@ public: | |||
|         a(m), | ||||
|         m_rewriter(m), | ||||
|         bp(nm, m_alloc, p), | ||||
|         m_interval(m.limit()), | ||||
|         m_interval(m_dep_manager, m.limit()), | ||||
|         m_trail(m), | ||||
|         m_num_buffer(nm) { | ||||
|         updt_params(p); | ||||
|  |  | |||
|  | @ -59,9 +59,10 @@ namespace dd { | |||
|         | ||||
|     */ | ||||
| 
 | ||||
|     solver::solver(reslimit& lim, pdd_manager& m) :  | ||||
|     solver::solver(reslimit& lim, u_dependency_manager& dm, pdd_manager& m) :  | ||||
|         m(m), | ||||
|         m_limit(lim)  | ||||
|         m_limit(lim), | ||||
|         m_dep_manager(dm) | ||||
|     {} | ||||
| 
 | ||||
|     solver::~solver() { | ||||
|  |  | |||
|  | @ -112,6 +112,7 @@ private: | |||
| 
 | ||||
|     pdd_manager&                                 m; | ||||
|     reslimit&                                    m_limit; | ||||
|     u_dependency_manager&                        m_dep_manager; | ||||
|     stats                                        m_stats; | ||||
|     config                                       m_config; | ||||
|     print_dep_t                                  m_print_dep; | ||||
|  | @ -119,12 +120,11 @@ private: | |||
|     equation_vector                              m_processed; | ||||
|     equation_vector                              m_to_simplify; | ||||
|     vector<std::tuple<unsigned, pdd, u_dependency*>> m_subst; | ||||
|     mutable u_dependency_manager                 m_dep_manager; | ||||
|     equation_vector                              m_all_eqs; | ||||
|     equation*                                    m_conflict = nullptr;    | ||||
|     bool                                         m_too_complex; | ||||
| public: | ||||
|     solver(reslimit& lim, pdd_manager& m); | ||||
|     solver(reslimit& lim, u_dependency_manager& dm, pdd_manager& m); | ||||
|     ~solver(); | ||||
| 
 | ||||
|     pdd_manager& get_manager() { return m; } | ||||
|  | @ -144,7 +144,6 @@ public: | |||
|     void saturate(); | ||||
| 
 | ||||
|     equation_vector const& equations(); | ||||
|     u_dependency_manager& dep() const { return m_dep_manager;  } | ||||
| 
 | ||||
|     void collect_statistics(statistics & st) const; | ||||
|     std::ostream& display(std::ostream& out, const equation& eq) const; | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ | |||
| #include "math/interval/interval.h" | ||||
| 
 | ||||
| class dep_intervals { | ||||
| 
 | ||||
| public: | ||||
|     enum with_deps_t { with_deps, without_deps }; | ||||
| 
 | ||||
|  | @ -142,8 +143,9 @@ private: | |||
| public: | ||||
|     typedef interval_manager<im_config>::interval interval; | ||||
| 
 | ||||
|     u_dependency_manager&               m_dep_manager; | ||||
|     mutable unsynch_mpq_manager         m_num_manager; | ||||
|     mutable u_dependency_manager        m_dep_manager; | ||||
| 
 | ||||
|     im_config                           m_config; | ||||
|     mutable interval_manager<im_config> m_imanager; | ||||
| 
 | ||||
|  | @ -158,9 +160,10 @@ public: | |||
| public: | ||||
|     u_dependency_manager& dep_manager() { return m_dep_manager; } | ||||
| 
 | ||||
|     dep_intervals(reslimit& lim) : | ||||
|         m_config(m_num_manager, m_dep_manager), | ||||
|         m_imanager(lim, im_config(m_num_manager, m_dep_manager)) | ||||
|     dep_intervals(u_dependency_manager& dm, reslimit& lim) : | ||||
|         m_dep_manager(dm), | ||||
|         m_config(m_num_manager, dm), | ||||
|         m_imanager(lim, im_config(m_num_manager, dm)) | ||||
|     {} | ||||
| 
 | ||||
|     std::ostream& display(std::ostream& out, const interval& i) const; | ||||
|  | @ -335,15 +338,17 @@ public: | |||
| 
 | ||||
|     bool is_empty(interval const& a) const; | ||||
|     void set_interval_for_scalar(interval&, const rational&); | ||||
| 
 | ||||
|     template <typename T>  | ||||
|     void linearize(u_dependency* dep, T& expl) const { | ||||
|         vector<unsigned, false> v; | ||||
|         m_dep_manager.linearize(dep, v); | ||||
|         for (unsigned ci: v) | ||||
|         for (auto ci: v) | ||||
|             expl.push_back(ci); | ||||
|     } | ||||
| 
 | ||||
|     void reset() { m_dep_manager.reset(); } | ||||
| 
 | ||||
|     void reset() { } | ||||
| 
 | ||||
|     void del(interval& i) { m_imanager.del(i); } | ||||
|      | ||||
|  |  | |||
|  | @ -517,11 +517,10 @@ bool emonics::invariant() const { | |||
|     TRACE("nla_solver_mons", display(tout);); | ||||
|     // the variable index contains exactly the active monomials
 | ||||
|     unsigned mons = 0; | ||||
|     for (lpvar v = 0; v < m_var2index.size(); v++) { | ||||
|         if (is_monic_var(v)) { | ||||
|     for (lpvar v = 0; v < m_var2index.size(); v++) | ||||
|         if (is_monic_var(v))  | ||||
|             mons++; | ||||
|         } | ||||
|     } | ||||
|              | ||||
|     if (m_monics.size() != mons) { | ||||
|         TRACE("nla_solver_mons", tout << "missmatch of monic vars\n";); | ||||
|         return false; | ||||
|  |  | |||
|  | @ -50,9 +50,13 @@ class create_cut { | |||
|     bool at_upper(unsigned j) const { return lia.at_upper(j); } | ||||
|     const impq & lower_bound(unsigned j) const { return lia.lower_bound(j); } | ||||
|     const impq & upper_bound(unsigned j) const  { return lia.upper_bound(j); } | ||||
|     constraint_index column_lower_bound_constraint(unsigned j) const { return lia.column_lower_bound_constraint(j); } | ||||
|     constraint_index column_upper_bound_constraint(unsigned j) const { return lia.column_upper_bound_constraint(j); } | ||||
|     u_dependency* column_lower_bound_constraint(unsigned j) const { return lia.column_lower_bound_constraint(j); } | ||||
|     u_dependency* column_upper_bound_constraint(unsigned j) const { return lia.column_upper_bound_constraint(j); } | ||||
|     bool column_is_fixed(unsigned j) const { return lia.lra.column_is_fixed(j); } | ||||
|     void push_explanation(u_dependency* d) { | ||||
|         for (auto ci : lia.lra.flatten(d)) | ||||
|             m_ex->push_back(ci); | ||||
|     } | ||||
| 
 | ||||
|     void int_case_in_gomory_cut(unsigned j) { | ||||
|         lp_assert(is_int(j) && m_fj.is_pos()); | ||||
|  | @ -67,7 +71,7 @@ class create_cut { | |||
|             new_a = m_fj <= m_one_minus_f ? m_fj / m_one_minus_f : ((1 - m_fj) / m_f); | ||||
|             lp_assert(new_a.is_pos()); | ||||
|             m_k.addmul(new_a, lower_bound(j).x); | ||||
|             m_ex->push_back(column_lower_bound_constraint(j));             | ||||
|             push_explanation(column_lower_bound_constraint(j));             | ||||
|         } | ||||
|         else { | ||||
|             lp_assert(at_upper(j)); | ||||
|  | @ -75,7 +79,7 @@ class create_cut { | |||
|             new_a = - (m_fj <= m_f ? m_fj / m_f  : ((1 - m_fj) / m_one_minus_f)); | ||||
|             lp_assert(new_a.is_neg()); | ||||
|             m_k.addmul(new_a, upper_bound(j).x); | ||||
|             m_ex->push_back(column_upper_bound_constraint(j)); | ||||
|             push_explanation(column_upper_bound_constraint(j)); | ||||
|         } | ||||
|         m_t.add_monomial(new_a, j); | ||||
|         m_lcm_den = lcm(m_lcm_den, denominator(new_a)); | ||||
|  | @ -99,7 +103,7 @@ class create_cut { | |||
|                 new_a = - a / m_f; | ||||
|             m_k.addmul(new_a, lower_bound(j).x); // is it a faster operation than
 | ||||
|             // k += lower_bound(j).x * new_a;  
 | ||||
|             m_ex->push_back(column_lower_bound_constraint(j)); | ||||
|             push_explanation(column_lower_bound_constraint(j)); | ||||
|         } | ||||
|         else { | ||||
|             lp_assert(at_upper(j)); | ||||
|  | @ -110,7 +114,7 @@ class create_cut { | |||
|                 // the delta is positive works again m_one_minus_f
 | ||||
|                 new_a =   a / m_one_minus_f;  | ||||
|             m_k.addmul(new_a, upper_bound(j).x); //  k += upper_bound(j).x * new_a; 
 | ||||
|             m_ex->push_back(column_upper_bound_constraint(j)); | ||||
|             push_explanation(column_upper_bound_constraint(j)); | ||||
|         } | ||||
|         m_t.add_monomial(new_a, j); | ||||
|         TRACE("gomory_cut_detail_real", tout << "add " << new_a << "*v" << j << ", k: " << m_k << "\n"; | ||||
|  | @ -313,8 +317,8 @@ public: | |||
|              // use -p.coeff() to make the format compatible with the format used in: Integrating Simplex with DPLL(T)
 | ||||
|             try { | ||||
|                 if (lia.is_fixed(j)) { | ||||
|                     m_ex->push_back(column_lower_bound_constraint(j)); | ||||
|                     m_ex->push_back(column_upper_bound_constraint(j)); | ||||
|                     push_explanation(column_lower_bound_constraint(j)); | ||||
|                     push_explanation(column_upper_bound_constraint(j)); | ||||
|                     continue; | ||||
|                 } | ||||
|                 if (is_real(j))    | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ namespace lp  { | |||
|         m_overflow = false; | ||||
|     } | ||||
| 
 | ||||
|     void hnf_cutter::add_term(const lar_term* t, const mpq &rs, constraint_index ci, bool upper_bound) { | ||||
|     void hnf_cutter::add_term(const lar_term* t, const mpq &rs, u_dependency* ci, bool upper_bound) { | ||||
|         m_terms.push_back(t); | ||||
|         m_terms_upper.push_back(upper_bound); | ||||
|         if (upper_bound) | ||||
|  | @ -146,7 +146,7 @@ namespace lp  { | |||
|     } | ||||
| #endif | ||||
|     void hnf_cutter::shrink_explanation(const svector<unsigned>& basis_rows) { | ||||
|         svector<unsigned> new_expl; | ||||
|         ptr_vector<u_dependency> new_expl; | ||||
|         for (unsigned i : basis_rows) { | ||||
|             new_expl.push_back(m_constraints_for_explanation[i]); | ||||
|         } | ||||
|  | @ -232,10 +232,10 @@ branch y_i >= ceil(y0_i) is impossible. | |||
|     void hnf_cutter::try_add_term_to_A_for_hnf(tv const &i) { | ||||
|         mpq rs; | ||||
|         const lar_term& t = lra.get_term(i); | ||||
|         constraint_index ci; | ||||
|         u_dependency* dep; | ||||
|         bool upper_bound; | ||||
|         if (!is_full() && lra.get_equality_and_right_side_for_term_on_current_x(i, rs, ci, upper_bound)) { | ||||
|             add_term(&t, rs, ci, upper_bound); | ||||
|         if (!is_full() && lra.get_equality_and_right_side_for_term_on_current_x(i, rs, dep, upper_bound)) { | ||||
|             add_term(&t, rs, dep, upper_bound); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -259,8 +259,9 @@ branch y_i >= ceil(y0_i) is impossible. | |||
|         } | ||||
|         lia.settings().stats().m_hnf_cutter_calls++; | ||||
|         TRACE("hnf_cut", tout << "settings().stats().m_hnf_cutter_calls = " << lia.settings().stats().m_hnf_cutter_calls << "\n"; | ||||
|               for (unsigned i : constraints_for_explanation()) { | ||||
|                   lra.constraints().display(tout, i); | ||||
|               for (u_dependency* d : constraints_for_explanation()) { | ||||
|                 for (auto ci : lra.flatten(d)) | ||||
|                   lra.constraints().display(tout, ci); | ||||
|               }               | ||||
|               tout << lra.constraints(); | ||||
|               ); | ||||
|  | @ -277,16 +278,16 @@ branch y_i >= ceil(y0_i) is impossible. | |||
|             TRACE("hnf_cut", | ||||
|                   lra.print_term(lia.m_t, tout << "cut:");  | ||||
|                   tout << " <= " << lia.m_k << std::endl; | ||||
|                   for (unsigned i : constraints_for_explanation()) { | ||||
|                       lra.constraints().display(tout, i); | ||||
|                   }               | ||||
|                   for (auto* dep : constraints_for_explanation())  | ||||
|                       for (auto ci : lra.flatten(dep)) | ||||
|                         lra.constraints().display(tout, ci);                   | ||||
|                   ); | ||||
|             lp_assert(lia.current_solution_is_inf_on_cut()); | ||||
|             lia.settings().stats().m_hnf_cuts++; | ||||
|             lia.m_ex->clear();         | ||||
|             for (unsigned i : constraints_for_explanation()) { | ||||
|                 lia.m_ex->push_back(i); | ||||
|             } | ||||
|             for (u_dependency* dep : constraints_for_explanation())  | ||||
|                 for (auto ci : lia.lra.flatten(dep)) | ||||
|                     lia.m_ex->push_back(ci);             | ||||
|         }  | ||||
|         return r; | ||||
|     } | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ class hnf_cutter { | |||
|     general_matrix             m_A; | ||||
|     vector<const lar_term*>    m_terms; | ||||
|     vector<bool>               m_terms_upper; | ||||
|     svector<constraint_index>  m_constraints_for_explanation; | ||||
|     ptr_vector<u_dependency>  m_constraints_for_explanation; | ||||
|     vector<mpq>                m_right_sides; | ||||
|     mpq                        m_abs_max; | ||||
|     bool                       m_overflow; | ||||
|  | @ -55,13 +55,13 @@ private: | |||
|     unsigned terms_count() const { return m_terms.size();  } | ||||
|     const mpq & abs_max() const { return m_abs_max; } | ||||
|     const vector<const lar_term*>& terms() const { return m_terms; } | ||||
|     const svector<unsigned>& constraints_for_explanation() const { return m_constraints_for_explanation; } | ||||
|     const ptr_vector<u_dependency>& constraints_for_explanation() const { return m_constraints_for_explanation; } | ||||
|     const vector<mpq> & right_sides() const { return m_right_sides; } | ||||
| 
 | ||||
|     bool is_full() const; | ||||
| 
 | ||||
|     void clear(); | ||||
|     void add_term(const lar_term* t, const mpq &rs, constraint_index ci, bool upper_bound); | ||||
|     void add_term(const lar_term* t, const mpq &rs, u_dependency* ci, bool upper_bound); | ||||
|      | ||||
|     void print(std::ostream & out); | ||||
| 
 | ||||
|  |  | |||
|  | @ -103,7 +103,7 @@ bool horner::horner_lemmas() { | |||
|         return false; | ||||
|     } | ||||
|     c().lp_settings().stats().m_horner_calls++; | ||||
|     const auto& matrix = c().m_lar_solver.A_r(); | ||||
|     const auto& matrix = c().lra.A_r(); | ||||
|     // choose only rows that depend on m_to_refine variables
 | ||||
|     std::set<unsigned> rows_to_check; | ||||
|     for (lpvar j : c().m_to_refine) { | ||||
|  |  | |||
|  | @ -250,10 +250,9 @@ namespace lp { | |||
|     } | ||||
| 
 | ||||
|     void int_gcd_test::add_to_explanation_from_fixed_or_boxed_column(unsigned j) { | ||||
|         constraint_index lc, uc; | ||||
|         lra.get_bound_constraint_witnesses_for_column(j, lc, uc); | ||||
|         lia.m_ex->push_back(lc); | ||||
|         lia.m_ex->push_back(uc); | ||||
|         auto* deps = lra.get_bound_constraint_witnesses_for_column(j); | ||||
|         for (auto d : lra.flatten(deps)) | ||||
|             lia.m_ex->push_back(d); | ||||
|     } | ||||
| 
 | ||||
|     bool int_gcd_test::accumulate_parity(const row_strip<mpq> & row, unsigned least_idx) { | ||||
|  |  | |||
|  | @ -242,11 +242,11 @@ namespace lp { | |||
|         return lra.has_inf_int(); | ||||
|     } | ||||
| 
 | ||||
|     constraint_index int_solver::column_upper_bound_constraint(unsigned j) const { | ||||
|     u_dependency* int_solver::column_upper_bound_constraint(unsigned j) const { | ||||
|         return lra.get_column_upper_bound_witness(j); | ||||
|     } | ||||
| 
 | ||||
|     constraint_index int_solver::column_lower_bound_constraint(unsigned j) const { | ||||
|     u_dependency* int_solver::column_lower_bound_constraint(unsigned j) const { | ||||
|         return lra.get_column_lower_bound_witness(j); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -113,8 +113,8 @@ private: | |||
|      | ||||
| public: | ||||
|     std::ostream& display_column(std::ostream & out, unsigned j) const; | ||||
|     constraint_index column_upper_bound_constraint(unsigned j) const; | ||||
|     constraint_index column_lower_bound_constraint(unsigned j) const; | ||||
|     u_dependency* column_upper_bound_constraint(unsigned j) const; | ||||
|     u_dependency* column_lower_bound_constraint(unsigned j) const; | ||||
|     bool current_solution_is_inf_on_cut() const; | ||||
| 
 | ||||
|     bool shift_var(unsigned j, unsigned range); | ||||
|  |  | |||
|  | @ -1,21 +1,10 @@ | |||
| /*++
 | ||||
| Copyright (c) 2017 Microsoft Corporation | ||||
| 
 | ||||
| Module Name: | ||||
| 
 | ||||
|     <name> | ||||
| 
 | ||||
| Abstract: | ||||
| 
 | ||||
|     <abstract> | ||||
| 
 | ||||
| Author: | ||||
| 
 | ||||
|     Lev Nachmanson (levnach) | ||||
| 
 | ||||
| Revision History: | ||||
| 
 | ||||
| 
 | ||||
| --*/ | ||||
| 
 | ||||
| #pragma once | ||||
|  | @ -53,15 +42,19 @@ class lar_base_constraint { | |||
|     mpq              m_right_side; | ||||
|     bool             m_active; | ||||
|     unsigned         m_j; | ||||
| public: | ||||
|     u_dependency*    m_dep; | ||||
| 
 | ||||
|    public: | ||||
| 
 | ||||
|     virtual vector<std::pair<mpq, var_index>> coeffs() const = 0; | ||||
|     lar_base_constraint(unsigned j, lconstraint_kind kind, const mpq& right_side) :m_kind(kind), m_right_side(right_side), m_active(false), m_j(j) {} | ||||
|     lar_base_constraint(unsigned j, lconstraint_kind kind, u_dependency* dep, const mpq& right_side) : | ||||
|         m_kind(kind), m_right_side(right_side), m_active(false), m_j(j), m_dep(dep) {} | ||||
|     virtual ~lar_base_constraint() = default; | ||||
| 
 | ||||
|     lconstraint_kind kind() const { return m_kind; } | ||||
|     mpq const& rhs() const { return m_right_side; } | ||||
|     unsigned column() const { return m_j; } | ||||
|     u_dependency* dep() const { return m_dep; } | ||||
| 
 | ||||
|     void activate() { m_active = true; } | ||||
|     void deactivate() { m_active = false; } | ||||
|  | @ -73,8 +66,8 @@ public: | |||
| 
 | ||||
| class lar_var_constraint: public lar_base_constraint { | ||||
| public: | ||||
|     lar_var_constraint(unsigned j, lconstraint_kind kind, const mpq& right_side) :  | ||||
|         lar_base_constraint(j, kind, right_side) {} | ||||
|     lar_var_constraint(unsigned j, lconstraint_kind kind, u_dependency* dep, const mpq& right_side) :  | ||||
|         lar_base_constraint(j, kind, dep, right_side) {} | ||||
| 
 | ||||
|     vector<std::pair<mpq, var_index>> coeffs() const override { | ||||
|         vector<std::pair<mpq, var_index>> ret; | ||||
|  | @ -88,8 +81,8 @@ public: | |||
| class lar_term_constraint: public lar_base_constraint { | ||||
|     const lar_term * m_term; | ||||
| public: | ||||
|     lar_term_constraint(unsigned j, const lar_term *t, lconstraint_kind kind, const mpq& right_side) :  | ||||
|         lar_base_constraint(j, kind, right_side), m_term(t) {} | ||||
|     lar_term_constraint(unsigned j, const lar_term* t, lconstraint_kind kind, u_dependency* dep, const mpq& right_side) :  | ||||
|         lar_base_constraint(j, kind, dep, right_side), m_term(t) {} | ||||
| 
 | ||||
|     vector<std::pair<mpq, var_index>> coeffs() const override { return m_term->coeffs_as_vector(); } | ||||
|     unsigned size() const override { return m_term->size();} | ||||
|  | @ -98,10 +91,11 @@ public: | |||
| class constraint_set { | ||||
|     region                         m_region; | ||||
|     column_namer&                  m_namer; | ||||
|     u_dependency_manager&          m_dep_manager; | ||||
|     vector<lar_base_constraint*>   m_constraints; | ||||
|     stacked_value<unsigned>        m_constraint_count; | ||||
|     unsigned_vector                m_active; | ||||
|     stacked_value<unsigned>        m_active_lim; | ||||
|     stacked_value<unsigned>        m_active_lim;     | ||||
| 
 | ||||
|     constraint_index add(lar_base_constraint* c) { | ||||
|         constraint_index ci = m_constraints.size(); | ||||
|  | @ -137,8 +131,13 @@ class constraint_set { | |||
|         return out << "constraint " << T_to_string(ci) << " is not found" << std::endl; | ||||
|     } | ||||
| 
 | ||||
|     u_dependency* mk_dep() { | ||||
|         return m_dep_manager.mk_leaf(m_constraints.size()); | ||||
|     } | ||||
| 
 | ||||
| public: | ||||
|     constraint_set(column_namer& cn):  | ||||
|     constraint_set(u_dependency_manager& d, column_namer& cn):  | ||||
|         m_dep_manager(d), | ||||
|         m_namer(cn) {} | ||||
| 
 | ||||
|     ~constraint_set() { | ||||
|  | @ -169,11 +168,12 @@ public: | |||
|     } | ||||
| 
 | ||||
|     constraint_index add_var_constraint(var_index j, lconstraint_kind k, mpq const& rhs) { | ||||
|         return add(new (m_region) lar_var_constraint(j, k, rhs)); | ||||
|         return add(new (m_region) lar_var_constraint(j, k, mk_dep(), rhs)); | ||||
|     } | ||||
| 
 | ||||
|     constraint_index add_term_constraint(unsigned j, const lar_term* t, lconstraint_kind k, mpq const& rhs) { | ||||
|         return add(new (m_region) lar_term_constraint(j, t, k, rhs)); | ||||
|         auto* dep = mk_dep(); | ||||
|         return add(new (m_region) lar_term_constraint(j, t, k, dep, rhs)); | ||||
|     } | ||||
| 
 | ||||
|     // future behavior uses activation bit.
 | ||||
|  |  | |||
|  | @ -21,9 +21,10 @@ class lar_core_solver  { | |||
|     int m_infeasible_sum_sign; // todo: get rid of this field
 | ||||
|     vector<numeric_pair<mpq>> m_right_sides_dummy; | ||||
|     vector<mpq> m_costs_dummy; | ||||
|      | ||||
| public: | ||||
|     stacked_value<simplex_strategy_enum> m_stacked_simplex_strategy; | ||||
| 
 | ||||
| public: | ||||
|      | ||||
|     stacked_vector<column_type> m_column_types; | ||||
|     // r - solver fields, for rational numbers
 | ||||
|     vector<numeric_pair<mpq>> m_r_x; // the solution
 | ||||
|  | @ -43,8 +44,6 @@ public: | |||
|                     const column_namer & column_names | ||||
|                     ); | ||||
| 
 | ||||
|     lp_settings & settings() { return m_r_solver.m_settings;} | ||||
| 
 | ||||
|     const lp_settings & settings() const { return m_r_solver.m_settings;} | ||||
|      | ||||
|     int get_infeasible_sum_sign() const { return m_infeasible_sum_sign;   } | ||||
|  | @ -57,8 +56,7 @@ public: | |||
|     void fill_not_improvable_zero_sum_from_inf_row(); | ||||
|      | ||||
|     column_type get_column_type(unsigned j) { return m_column_types[j];} | ||||
|      | ||||
|      | ||||
|          | ||||
|     void print_pivot_row(std::ostream & out, unsigned row_index) const  { | ||||
|         for (unsigned j : m_r_solver.m_pivot_row.m_index) { | ||||
|             if (numeric_traits<mpq>::is_pos(m_r_solver.m_pivot_row.m_data[j])) | ||||
|  | @ -68,9 +66,9 @@ public: | |||
|          | ||||
|         out << " +" << m_r_solver.column_name(m_r_solver.m_basis[row_index]) << std::endl; | ||||
|          | ||||
|         for (unsigned j : m_r_solver.m_pivot_row.m_index) { | ||||
|         for (unsigned j : m_r_solver.m_pivot_row.m_index)  | ||||
|             m_r_solver.print_column_bound_info(j, out); | ||||
|         } | ||||
|          | ||||
|         m_r_solver.print_column_bound_info(m_r_solver.m_basis[row_index], out);         | ||||
|     } | ||||
|      | ||||
|  | @ -110,10 +108,7 @@ public: | |||
|         m_column_types.push(); | ||||
|         // rational
 | ||||
|         m_r_lower_bounds.push(); | ||||
|         m_r_upper_bounds.push(); | ||||
|          | ||||
|          | ||||
|          | ||||
|         m_r_upper_bounds.push();         | ||||
|     } | ||||
| 
 | ||||
|     void pop(unsigned k) { | ||||
|  | @ -127,11 +122,9 @@ public: | |||
|         m_r_solver.m_d.resize(m_r_A.column_count()); | ||||
|          | ||||
|         m_stacked_simplex_strategy.pop(k); | ||||
|         settings().set_simplex_strategy(m_stacked_simplex_strategy); | ||||
|         m_r_solver.m_settings.set_simplex_strategy(m_stacked_simplex_strategy); | ||||
|         lp_assert(m_r_solver.basis_heading_is_correct()); | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|      | ||||
|     bool r_basis_is_OK() const { | ||||
| #ifdef Z3DEBUG | ||||
|  |  | |||
|  | @ -88,19 +88,18 @@ void lar_core_solver::solve() { | |||
|     lp_assert(m_r_solver.inf_heap_is_correct()); | ||||
| 	TRACE("find_feas_stats", tout << "infeasibles = " << m_r_solver.inf_heap_size() << ", int_infs = " << get_number_of_non_ints() << std::endl;); | ||||
| 	if (m_r_solver.current_x_is_feasible() && m_r_solver.m_look_for_feasible_solution_only) { | ||||
|             m_r_solver.set_status(lp_status::OPTIMAL); | ||||
|             TRACE("lar_solver", tout << m_r_solver.get_status() << "\n";); | ||||
|             return; | ||||
|         m_r_solver.set_status(lp_status::OPTIMAL); | ||||
|         TRACE("lar_solver", tout << m_r_solver.get_status() << "\n";); | ||||
|         return; | ||||
| 	} | ||||
|     ++settings().stats().m_need_to_solve_inf; | ||||
|     ++m_r_solver.m_settings.stats().m_need_to_solve_inf; | ||||
|     lp_assert( r_basis_is_OK()); | ||||
|       | ||||
|          | ||||
|               | ||||
|     if (m_r_solver.m_look_for_feasible_solution_only) //todo : should it be set?
 | ||||
|          m_r_solver.find_feasible_solution(); | ||||
|     else { | ||||
|     else  | ||||
|         m_r_solver.solve(); | ||||
|     } | ||||
|      | ||||
|     lp_assert(r_basis_is_OK()); | ||||
|      | ||||
|     switch (m_r_solver.get_status()) | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ namespace lp { | |||
|         m_mpq_lar_core_solver(m_settings, *this), | ||||
|         m_var_register(false), | ||||
|         m_term_register(true), | ||||
|         m_constraints(*this) {} | ||||
|         m_constraints(m_dependencies, *this) {} | ||||
| 
 | ||||
|     // start or ends tracking the rows that were changed by solve()
 | ||||
|     void lar_solver::track_touched_rows(bool v) { | ||||
|  | @ -218,8 +218,14 @@ namespace lp { | |||
| 
 | ||||
|         // this is the case when the lower bound is in conflict with the upper one
 | ||||
|         const ul_pair& ul = m_columns_to_ul_pairs[m_crossed_bounds_column]; | ||||
|         evidence.add_pair(ul.upper_bound_witness(), numeric_traits<mpq>::one()); | ||||
|         evidence.add_pair(ul.lower_bound_witness(), -numeric_traits<mpq>::one()); | ||||
|         svector<constraint_index> deps; | ||||
|         m_dependencies.linearize(ul.upper_bound_witness(), deps); | ||||
|         for (auto d : deps) | ||||
|             evidence.add_pair(d, numeric_traits<mpq>::one()); | ||||
|         deps.reset(); | ||||
|         m_dependencies.linearize(ul.lower_bound_witness(), deps); | ||||
|         for (auto d : deps) | ||||
|             evidence.add_pair(d, -numeric_traits<mpq>::one()); | ||||
|     } | ||||
| 
 | ||||
|     void lar_solver::push() { | ||||
|  | @ -232,6 +238,7 @@ namespace lp { | |||
|         m_term_count.push(); | ||||
|         m_constraints.push(); | ||||
|         m_usage_in_terms.push(); | ||||
|         m_dependencies.push_scope(); | ||||
|     } | ||||
|      | ||||
|     void lar_solver::clean_popped_elements(unsigned n, indexed_uint_set& set) { | ||||
|  | @ -297,6 +304,7 @@ namespace lp { | |||
|         lp_assert(sizes_are_correct()); | ||||
|         lp_assert(m_mpq_lar_core_solver.m_r_solver.reduced_costs_are_correct_tableau()); | ||||
|         m_usage_in_terms.pop(k); | ||||
|         m_dependencies.pop_scope(k); | ||||
|         set_status(lp_status::UNKNOWN); | ||||
|     } | ||||
| 
 | ||||
|  | @ -320,6 +328,39 @@ namespace lp { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     bool lar_solver::improve_bound(lpvar j, bool improve_lower_bound) { | ||||
|         lar_term term = get_term_to_maximize(j); | ||||
|         if (improve_lower_bound) | ||||
|             term.negate(); | ||||
|         impq bound; | ||||
|         if (!maximize_term_on_tableau(term, bound)) | ||||
|             return false; | ||||
|          | ||||
|         return false; | ||||
|         // TODO
 | ||||
|         if (improve_lower_bound) { | ||||
|             if (column_has_lower_bound(j) && bound.x == column_lower_bound(j).x) | ||||
|                 return false; | ||||
|             SASSERT(!column_has_lower_bound(j) || column_lower_bound(j).x < bound.x); | ||||
|              | ||||
|             // TODO - explain new lower bound.
 | ||||
|             // Seems the relevant information is in the "costs" that are used when 
 | ||||
|             // setting the optimization objecive. The costs are cleared after a call so
 | ||||
|             // maybe have some way of extracting bound dependencies from the costs.
 | ||||
|             u_dependency* dep = nullptr; | ||||
|             update_column_type_and_bound(j, bound.y > 0 ? lconstraint_kind::GT : lconstraint_kind::GE, bound.x, dep); | ||||
|         }  | ||||
|         else { | ||||
|             if (column_has_upper_bound(j) && bound.x == column_upper_bound(j).x) | ||||
|                 return false; | ||||
|             SASSERT(!column_has_upper_bound(j) || column_upper_bound(j).x > bound.x); | ||||
|             // similar for upper bounds
 | ||||
|             u_dependency* dep = nullptr; | ||||
|             update_column_type_and_bound(j, bound.y < 0 ? lconstraint_kind::LT : lconstraint_kind::LE, bound.x, dep); | ||||
|         } | ||||
|         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++) { | ||||
|             lp_assert(is_zero(m_mpq_lar_core_solver.m_r_solver.m_costs[j])); | ||||
|  | @ -349,7 +390,7 @@ namespace lp { | |||
|                     jset.insert(rc.var()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|          | ||||
|         for (unsigned j : jset) | ||||
|             rslv.m_d[j] = zero_of_type<mpq>(); | ||||
| 
 | ||||
|  | @ -577,15 +618,15 @@ namespace lp { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void lar_solver::set_upper_bound_witness(var_index j, constraint_index ci) { | ||||
|     void lar_solver::set_upper_bound_witness(var_index j, u_dependency* dep) { | ||||
|         ul_pair ul = m_columns_to_ul_pairs[j]; | ||||
|         ul.upper_bound_witness() = ci; | ||||
|         ul.upper_bound_witness() = dep; | ||||
|         m_columns_to_ul_pairs[j] = ul; | ||||
|     } | ||||
| 
 | ||||
|     void lar_solver::set_lower_bound_witness(var_index j, constraint_index ci) { | ||||
|     void lar_solver::set_lower_bound_witness(var_index j, u_dependency* dep) { | ||||
|         ul_pair ul = m_columns_to_ul_pairs[j]; | ||||
|         ul.lower_bound_witness() = ci; | ||||
|         ul.lower_bound_witness() = dep; | ||||
|         m_columns_to_ul_pairs[j] = ul; | ||||
|     } | ||||
| 
 | ||||
|  | @ -920,7 +961,7 @@ namespace lp { | |||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     bool lar_solver::has_lower_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) const { | ||||
|     bool lar_solver::has_lower_bound(var_index var, u_dependency*& ci, mpq& value, bool& is_strict) const { | ||||
| 
 | ||||
|         if (var >= m_columns_to_ul_pairs.size()) { | ||||
|             // TBD: bounds on terms could also be used, caller may have to track these.
 | ||||
|  | @ -928,7 +969,7 @@ namespace lp { | |||
|         } | ||||
|         const ul_pair& ul = m_columns_to_ul_pairs[var]; | ||||
|         ci = ul.lower_bound_witness(); | ||||
|         if (ci != null_ci) { | ||||
|         if (ci != nullptr) { | ||||
|             auto& p = m_mpq_lar_core_solver.m_r_lower_bounds()[var]; | ||||
|             value = p.x; | ||||
|             is_strict = p.y.is_pos(); | ||||
|  | @ -939,7 +980,7 @@ namespace lp { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     bool lar_solver::has_upper_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) const { | ||||
|     bool lar_solver::has_upper_bound(var_index var, u_dependency*& ci, mpq& value, bool& is_strict) const { | ||||
| 
 | ||||
|         if (var >= m_columns_to_ul_pairs.size()) { | ||||
|             // TBD: bounds on terms could also be used, caller may have to track these.
 | ||||
|  | @ -947,7 +988,7 @@ namespace lp { | |||
|         } | ||||
|         const ul_pair& ul = m_columns_to_ul_pairs[var]; | ||||
|         ci = ul.upper_bound_witness(); | ||||
|         if (ci != null_ci) { | ||||
|         if (ci != nullptr) { | ||||
|             auto& p = m_mpq_lar_core_solver.m_r_upper_bounds()[var]; | ||||
|             value = p.x; | ||||
|             is_strict = p.y.is_neg(); | ||||
|  | @ -1005,9 +1046,13 @@ namespace lp { | |||
|             int adj_sign = coeff.is_pos() ? inf_sign : -inf_sign; | ||||
|             const ul_pair& ul = m_columns_to_ul_pairs[j]; | ||||
| 
 | ||||
|             constraint_index bound_constr_i = adj_sign < 0 ? ul.upper_bound_witness() : ul.lower_bound_witness(); | ||||
|             lp_assert(m_constraints.valid_index(bound_constr_i)); | ||||
|             exp.add_pair(bound_constr_i, coeff); | ||||
|             u_dependency* bound_constr_i = adj_sign < 0 ? ul.upper_bound_witness() : ul.lower_bound_witness(); | ||||
|             svector<constraint_index> deps; | ||||
|             m_dependencies.linearize(bound_constr_i, deps); | ||||
|             for (auto d : deps) { | ||||
|                 lp_assert(m_constraints.valid_index(d)); | ||||
|                 exp.add_pair(d, coeff); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -1698,12 +1743,12 @@ namespace lp { | |||
| 
 | ||||
|     void lar_solver::activate_check_on_equal(constraint_index ci, unsigned& equal_column) { | ||||
|         auto const& c = m_constraints[ci]; | ||||
|         update_column_type_and_bound_check_on_equal(c.column(), c.kind(), c.rhs(), ci, equal_column); | ||||
|         update_column_type_and_bound_check_on_equal(c.column(), c.rhs(), ci, equal_column); | ||||
|     } | ||||
| 
 | ||||
|     void lar_solver::activate(constraint_index ci) { | ||||
|         auto const& c = m_constraints[ci]; | ||||
|         update_column_type_and_bound(c.column(), c.kind(), c.rhs(), ci); | ||||
|         update_column_type_and_bound(c.column(), c.rhs(), ci); | ||||
|     } | ||||
| 
 | ||||
|     mpq lar_solver::adjust_bound_for_int(lpvar j, lconstraint_kind& k, const mpq& bound) { | ||||
|  | @ -1765,31 +1810,37 @@ namespace lp { | |||
|     } | ||||
| 
 | ||||
|     void lar_solver::update_column_type_and_bound(unsigned j, | ||||
|         lconstraint_kind kind, | ||||
|         const mpq& right_side, | ||||
|         constraint_index constr_index) { | ||||
|         TRACE("lar_solver_feas", tout << "j = " << j << " was " << (this->column_is_feasible(j)?"feas":"non-feas") << std::endl;); | ||||
|         m_constraints.activate(constr_index); | ||||
|         if (column_has_upper_bound(j)) | ||||
|             update_column_type_and_bound_with_ub(j, kind, right_side, constr_index); | ||||
|         else | ||||
|             update_column_type_and_bound_with_no_ub(j, kind, right_side, constr_index); | ||||
| 
 | ||||
|         if (is_base(j) && column_is_fixed(j))  | ||||
|             m_fixed_base_var_set.insert(j); | ||||
|              | ||||
|         TRACE("lar_solver_feas", tout << "j = " << j << " became " << (this->column_is_feasible(j)?"feas":"non-feas") << ", and " << (this->column_is_bounded(j)? "bounded":"non-bounded") << std::endl;);     | ||||
|         lconstraint_kind kind = m_constraints[constr_index].kind(); | ||||
|         u_dependency* dep = m_constraints[constr_index].dep(); | ||||
|         update_column_type_and_bound(j, kind, right_side, dep); | ||||
|     } | ||||
| 
 | ||||
|     void lar_solver::update_column_type_and_bound(unsigned j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep) { | ||||
|         if (column_has_upper_bound(j)) | ||||
|             update_column_type_and_bound_with_ub(j, kind, right_side, dep); | ||||
|         else | ||||
|             update_column_type_and_bound_with_no_ub(j, kind, right_side, dep); | ||||
| 
 | ||||
|         if (is_base(j) && column_is_fixed(j)) | ||||
|             m_fixed_base_var_set.insert(j); | ||||
| 
 | ||||
|         TRACE("lar_solver_feas", tout << "j = " << j << " became " << (this->column_is_feasible(j) ? "feas" : "non-feas") << ", and " << (this->column_is_bounded(j) ? "bounded" : "non-bounded") << std::endl;);     | ||||
|     } | ||||
| 
 | ||||
|     void lar_solver::insert_to_columns_with_changed_bounds(unsigned j) { | ||||
|          m_columns_with_changed_bounds.insert(j); | ||||
|          TRACE("lar_solver", tout << "column " << j << (column_is_feasible(j) ? " feas" : " non-feas") << "\n";); | ||||
|     } | ||||
| 
 | ||||
|     void lar_solver::update_column_type_and_bound_check_on_equal(unsigned j, | ||||
|                                                                  lconstraint_kind kind, | ||||
|                                                                  const mpq& right_side, | ||||
|                                                                  constraint_index constr_index, | ||||
|                                                                  unsigned& equal_to_j) { | ||||
|         update_column_type_and_bound(j, kind, right_side, constr_index); | ||||
|         update_column_type_and_bound(j, right_side, constr_index); | ||||
|         equal_to_j = null_lpvar; | ||||
|         if (column_is_fixed(j)) { | ||||
|             register_in_fixed_var_table(j, equal_to_j); | ||||
|  | @ -1852,28 +1903,28 @@ namespace lp { | |||
|     } | ||||
| 
 | ||||
|      | ||||
|     void lar_solver::update_column_type_and_bound_with_ub(unsigned j, lp::lconstraint_kind kind, const mpq& right_side, unsigned constraint_index) { | ||||
|     void lar_solver::update_column_type_and_bound_with_ub(unsigned j, lp::lconstraint_kind kind, const mpq& right_side, u_dependency* dep) { | ||||
|         SASSERT(column_has_upper_bound(j)); | ||||
|         if (column_has_lower_bound(j)) { | ||||
|             update_bound_with_ub_lb(j, kind, right_side, constraint_index); | ||||
|             update_bound_with_ub_lb(j, kind, right_side, dep); | ||||
|         } | ||||
|         else { | ||||
|             update_bound_with_ub_no_lb(j, kind, right_side, constraint_index); | ||||
|             update_bound_with_ub_no_lb(j, kind, right_side, dep); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void lar_solver::update_column_type_and_bound_with_no_ub(unsigned j, lp::lconstraint_kind kind, const mpq& right_side, unsigned constraint_index) { | ||||
|     void lar_solver::update_column_type_and_bound_with_no_ub(unsigned j, lp::lconstraint_kind kind, const mpq& right_side, u_dependency* dep) { | ||||
|         SASSERT(!column_has_upper_bound(j)); | ||||
|         if (column_has_lower_bound(j)) { | ||||
|             update_bound_with_no_ub_lb(j, kind, right_side, constraint_index); | ||||
|             update_bound_with_no_ub_lb(j, kind, right_side, dep); | ||||
|         } | ||||
|         else { | ||||
|             update_bound_with_no_ub_no_lb(j, kind, right_side, constraint_index); | ||||
|             update_bound_with_no_ub_no_lb(j, kind, right_side, dep); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // clang-format on
 | ||||
|     void lar_solver::update_bound_with_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index ci) { | ||||
|     void lar_solver::update_bound_with_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep) { | ||||
|         lp_assert(column_has_lower_bound(j) && column_has_upper_bound(j)); | ||||
|         lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::boxed || | ||||
|                   m_mpq_lar_core_solver.m_column_types[j] == column_type::fixed); | ||||
|  | @ -1889,7 +1940,7 @@ namespace lp { | |||
|                 } | ||||
|                 if (up >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) return; | ||||
|                 m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|                 set_upper_bound_witness(j, dep); | ||||
|                 insert_to_columns_with_changed_bounds(j); | ||||
|                 break; | ||||
|             } | ||||
|  | @ -1904,7 +1955,7 @@ namespace lp { | |||
|                     return; | ||||
|                 } | ||||
|                 m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, dep); | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed); | ||||
|                 insert_to_columns_with_changed_bounds(j); | ||||
|                 break; | ||||
|  | @ -1914,8 +1965,8 @@ namespace lp { | |||
|                 if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j] || v < m_mpq_lar_core_solver.m_r_lower_bounds[j]) { | ||||
|                     set_infeasible_column(j); | ||||
|                 } | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|                 set_upper_bound_witness(j, dep); | ||||
|                 set_lower_bound_witness(j, dep); | ||||
|                 m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v; | ||||
|                 break; | ||||
|             } | ||||
|  | @ -1928,7 +1979,7 @@ namespace lp { | |||
|         } | ||||
|     } | ||||
|     // clang-format off
 | ||||
|     void lar_solver::update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index ci) { | ||||
|     void lar_solver::update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep) { | ||||
|         lp_assert(column_has_lower_bound(j) && !column_has_upper_bound(j)); | ||||
|         lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::lower_bound); | ||||
| 
 | ||||
|  | @ -1942,7 +1993,7 @@ namespace lp { | |||
|                     set_infeasible_column(j); | ||||
|                 } | ||||
|                 m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|                 set_upper_bound_witness(j, dep); | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = (up == m_mpq_lar_core_solver.m_r_lower_bounds[j] ? column_type::fixed : column_type::boxed); | ||||
|                 insert_to_columns_with_changed_bounds(j); | ||||
|                 break; | ||||
|  | @ -1955,7 +2006,7 @@ namespace lp { | |||
|                     return; | ||||
|                 } | ||||
|                 m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, dep); | ||||
|                 insert_to_columns_with_changed_bounds(j); | ||||
|                 break; | ||||
|             }  | ||||
|  | @ -1965,8 +2016,8 @@ namespace lp { | |||
|                     set_infeasible_column(j); | ||||
|                 } | ||||
| 
 | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|                 set_upper_bound_witness(j, dep); | ||||
|                 set_lower_bound_witness(j, dep); | ||||
|                 m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v; | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; | ||||
|                 break; | ||||
|  | @ -1977,7 +2028,7 @@ namespace lp { | |||
|         } | ||||
|     } | ||||
|     // clang-format off
 | ||||
|     void lar_solver::update_bound_with_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index ci) { | ||||
|     void lar_solver::update_bound_with_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep) { | ||||
|         lp_assert(!column_has_lower_bound(j) && column_has_upper_bound(j)); | ||||
|         lp_assert(m_mpq_lar_core_solver.m_column_types[j] == column_type::upper_bound); | ||||
|         mpq y_of_bound(0); | ||||
|  | @ -1989,7 +2040,7 @@ namespace lp { | |||
|             auto up = numeric_pair<mpq>(right_side, y_of_bound); | ||||
|             if (up >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) return; | ||||
|             m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; | ||||
|             set_upper_bound_witness(j, ci); | ||||
|             set_upper_bound_witness(j, dep); | ||||
|             insert_to_columns_with_changed_bounds(j); | ||||
|         } | ||||
|         break; | ||||
|  | @ -2002,7 +2053,7 @@ namespace lp { | |||
|                 set_infeasible_column(j); | ||||
|             } | ||||
|             m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; | ||||
|             set_lower_bound_witness(j, ci); | ||||
|             set_lower_bound_witness(j, dep); | ||||
|             m_mpq_lar_core_solver.m_column_types[j] = (low == m_mpq_lar_core_solver.m_r_upper_bounds[j] ? column_type::fixed : column_type::boxed); | ||||
|             insert_to_columns_with_changed_bounds(j); | ||||
|              | ||||
|  | @ -2015,8 +2066,8 @@ namespace lp { | |||
|                 set_infeasible_column(j); | ||||
|             } | ||||
| 
 | ||||
|             set_upper_bound_witness(j, ci); | ||||
|             set_lower_bound_witness(j, ci); | ||||
|             set_upper_bound_witness(j, dep); | ||||
|             set_lower_bound_witness(j, dep); | ||||
|             m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v; | ||||
|             m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; | ||||
|             break; | ||||
|  | @ -2027,7 +2078,7 @@ namespace lp { | |||
|         } | ||||
|     } | ||||
|     // clang-format on
 | ||||
|     void lar_solver::update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index ci) { | ||||
|     void lar_solver::update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep) { | ||||
|         lp_assert(!column_has_lower_bound(j) && !column_has_upper_bound(j)); | ||||
| 
 | ||||
|         mpq y_of_bound(0); | ||||
|  | @ -2037,7 +2088,7 @@ namespace lp { | |||
|             case LE: { | ||||
|                 auto up = numeric_pair<mpq>(right_side, y_of_bound); | ||||
|                 m_mpq_lar_core_solver.m_r_upper_bounds[j] = up; | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|                 set_upper_bound_witness(j, dep); | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = column_type::upper_bound; | ||||
|             } break; | ||||
|             case GT: | ||||
|  | @ -2045,14 +2096,14 @@ namespace lp { | |||
|             case GE: { | ||||
|                 auto low = numeric_pair<mpq>(right_side, y_of_bound); | ||||
|                 m_mpq_lar_core_solver.m_r_lower_bounds[j] = low; | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, dep); | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = column_type::lower_bound; | ||||
| 
 | ||||
|             } break; | ||||
|             case EQ: { | ||||
|                 auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>()); | ||||
|                 set_upper_bound_witness(j, ci); | ||||
|                 set_lower_bound_witness(j, ci); | ||||
|                 set_upper_bound_witness(j, dep); | ||||
|                 set_lower_bound_witness(j, dep); | ||||
|                 m_mpq_lar_core_solver.m_r_upper_bounds[j] = m_mpq_lar_core_solver.m_r_lower_bounds[j] = v; | ||||
|                 m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed; | ||||
|                 break; | ||||
|  | @ -2165,7 +2216,7 @@ namespace lp { | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     bool lar_solver::get_equality_and_right_side_for_term_on_current_x(tv const& t, mpq& rs, constraint_index& ci, bool& upper_bound) const { | ||||
|     bool lar_solver::get_equality_and_right_side_for_term_on_current_x(tv const& t, mpq& rs, u_dependency*& ci, bool& upper_bound) const { | ||||
|         lp_assert(t.is_term()); | ||||
|         unsigned j; | ||||
|         bool is_int; | ||||
|  |  | |||
|  | @ -47,6 +47,8 @@ namespace lp { | |||
| 
 | ||||
| class int_branch; | ||||
| class int_solver; | ||||
| 
 | ||||
|      | ||||
| class lar_solver : public column_namer { | ||||
|     struct term_hasher { | ||||
|         std::size_t operator()(const lar_term& t) const { | ||||
|  | @ -88,6 +90,8 @@ class lar_solver : public column_namer { | |||
|     indexed_uint_set m_columns_with_changed_bounds; | ||||
|     indexed_uint_set m_touched_rows; | ||||
|     unsigned_vector m_row_bounds_to_replay; | ||||
|     u_dependency_manager m_dependencies; | ||||
|     svector<constraint_index> m_tmp_dependencies; | ||||
| 
 | ||||
|     indexed_uint_set m_basic_columns_with_changed_cost; | ||||
|     // these are basic columns with the value changed, so the corresponding row in the tableau
 | ||||
|  | @ -136,14 +140,15 @@ class lar_solver : public column_namer { | |||
| 
 | ||||
|     inline void clear_columns_with_changed_bounds() { m_columns_with_changed_bounds.reset(); } | ||||
|     void insert_to_columns_with_changed_bounds(unsigned j); | ||||
|     void update_column_type_and_bound_check_on_equal(unsigned j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index, unsigned&); | ||||
|     void update_column_type_and_bound(unsigned j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index); | ||||
|     void update_column_type_and_bound_with_ub(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index); | ||||
|     void update_column_type_and_bound_with_no_ub(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index); | ||||
|     void update_bound_with_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index); | ||||
|     void update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index); | ||||
|     void update_bound_with_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index); | ||||
|     void update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index constr_index); | ||||
|     void update_column_type_and_bound_check_on_equal(unsigned j, const mpq& right_side, constraint_index ci, unsigned&); | ||||
|     void update_column_type_and_bound(unsigned j, const mpq& right_side, constraint_index ci); | ||||
|     void update_column_type_and_bound(unsigned j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); | ||||
|     void update_column_type_and_bound_with_ub(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); | ||||
|     void update_column_type_and_bound_with_no_ub(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); | ||||
|     void update_bound_with_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); | ||||
|     void update_bound_with_no_ub_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); | ||||
|     void update_bound_with_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); | ||||
|     void update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, u_dependency* dep); | ||||
|     void register_in_fixed_var_table(unsigned, unsigned&); | ||||
|     void remove_non_fixed_from_fixed_var_table(); | ||||
|     constraint_index add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq& right_side); | ||||
|  | @ -186,8 +191,8 @@ class lar_solver : public column_namer { | |||
|     bool maximize_term_on_corrected_r_solver(lar_term& term, impq& term_max); | ||||
|     void pop_core_solver_params(); | ||||
|     void pop_core_solver_params(unsigned k); | ||||
|     void set_upper_bound_witness(var_index j, constraint_index ci); | ||||
|     void set_lower_bound_witness(var_index j, constraint_index ci); | ||||
|     void set_upper_bound_witness(var_index j, u_dependency* ci); | ||||
|     void set_lower_bound_witness(var_index j, u_dependency* ci); | ||||
|     void substitute_terms_in_linear_expression(const vector<std::pair<mpq, var_index>>& left_side_with_terms, | ||||
|                                                vector<std::pair<mpq, var_index>>& left_side) const; | ||||
| 
 | ||||
|  | @ -283,6 +288,8 @@ class lar_solver : public column_namer { | |||
| 
 | ||||
|     lp_status maximize_term(unsigned j_or_term, impq& term_max); | ||||
| 
 | ||||
|     bool improve_bound(lpvar j, bool is_lower); | ||||
| 
 | ||||
|     inline core_solver_pretty_printer<lp::mpq, lp::impq> pp(std::ostream& out) const { | ||||
|         return core_solver_pretty_printer<lp::mpq, lp::impq>(m_mpq_lar_core_solver.m_r_solver, out); | ||||
|     } | ||||
|  | @ -310,9 +317,10 @@ class lar_solver : public column_namer { | |||
|             int a_sign = is_pos(a) ? 1 : -1; | ||||
|             int sign = j_sign * a_sign; | ||||
|             const ul_pair& ul = m_columns_to_ul_pairs[j]; | ||||
|             auto witness = sign > 0 ? ul.upper_bound_witness() : ul.lower_bound_witness(); | ||||
|             lp_assert(is_valid(witness)); | ||||
|             bp.consume(a, witness); | ||||
|             auto* witness = sign > 0 ? ul.upper_bound_witness() : ul.lower_bound_witness(); | ||||
|             lp_assert(witness); | ||||
|             for (auto ci : flatten(witness)) | ||||
|                 bp.consume(a, ci); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -460,7 +468,20 @@ class lar_solver : public column_namer { | |||
|         return m_mpq_lar_core_solver.m_r_solver.column_has_lower_bound(j); | ||||
|     } | ||||
| 
 | ||||
|     inline constraint_index get_column_upper_bound_witness(unsigned j) const { | ||||
|     svector<constraint_index> const& flatten(u_dependency* d) { | ||||
|         m_tmp_dependencies.reset(); | ||||
|         m_dependencies.linearize(d, m_tmp_dependencies); | ||||
|         return m_tmp_dependencies; | ||||
|     } | ||||
| 
 | ||||
|     void push_explanation(u_dependency* d, explanation& ex) { | ||||
|         for (auto ci : flatten(d)) | ||||
|             ex.push_back(ci); | ||||
|     } | ||||
| 
 | ||||
|     u_dependency_manager& dep_manager() { return m_dependencies; } | ||||
| 
 | ||||
|     inline u_dependency* get_column_upper_bound_witness(unsigned j) const { | ||||
|         if (tv::is_term(j)) { | ||||
|             j = m_var_register.external_to_local(j); | ||||
|         } | ||||
|  | @ -474,8 +495,8 @@ class lar_solver : public column_namer { | |||
|     inline const impq& get_lower_bound(column_index j) const { | ||||
|         return m_mpq_lar_core_solver.m_r_solver.m_lower_bounds[j]; | ||||
|     } | ||||
|     bool has_lower_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) const; | ||||
|     bool has_upper_bound(var_index var, constraint_index& ci, mpq& value, bool& is_strict) const; | ||||
|     bool has_lower_bound(var_index var, u_dependency*& ci, mpq& value, bool& is_strict) const; | ||||
|     bool has_upper_bound(var_index var, u_dependency*& ci, mpq& value, bool& is_strict) const; | ||||
|     bool has_value(var_index var, mpq& value) const; | ||||
|     bool fetch_normalized_term_column(const lar_term& t, std::pair<mpq, lpvar>&) const; | ||||
|     unsigned map_term_index_to_column_index(unsigned j) const; | ||||
|  | @ -530,15 +551,15 @@ class lar_solver : public column_namer { | |||
| 
 | ||||
|     std::pair<constraint_index, constraint_index> add_equality(lpvar j, lpvar k); | ||||
| 
 | ||||
|     inline void get_bound_constraint_witnesses_for_column(unsigned j, constraint_index& lc, constraint_index& uc) const { | ||||
|     u_dependency* get_bound_constraint_witnesses_for_column(unsigned j) { | ||||
|         const ul_pair& ul = m_columns_to_ul_pairs[j]; | ||||
|         lc = ul.lower_bound_witness(); | ||||
|         uc = ul.upper_bound_witness(); | ||||
|         return m_dependencies.mk_join(ul.lower_bound_witness(), ul.upper_bound_witness()); | ||||
|     } | ||||
|     inline constraint_set const& constraints() const { return m_constraints; } | ||||
|     void push(); | ||||
|     void pop(); | ||||
|     inline constraint_index get_column_lower_bound_witness(unsigned j) const { | ||||
| 
 | ||||
|     inline u_dependency* get_column_lower_bound_witness(unsigned j) const { | ||||
|         if (tv::is_term(j)) { | ||||
|             j = m_var_register.external_to_local(j); | ||||
|         } | ||||
|  | @ -601,7 +622,7 @@ class lar_solver : public column_namer { | |||
|     inline const column_strip& get_column(unsigned i) const { return A_r().m_columns[i]; } | ||||
|     bool row_is_correct(unsigned i) const; | ||||
|     bool ax_is_correct() const; | ||||
|     bool get_equality_and_right_side_for_term_on_current_x(tv const& t, mpq& rs, constraint_index& ci, bool& upper_bound) const; | ||||
|     bool get_equality_and_right_side_for_term_on_current_x(tv const& t, mpq& rs, u_dependency*& ci, bool& upper_bound) const; | ||||
|     bool var_is_int(var_index v) const; | ||||
|     inline const vector<int>& r_heading() const { return m_mpq_lar_core_solver.m_r_heading; } | ||||
|     inline const vector<unsigned>& r_basis() const { return m_mpq_lar_core_solver.r_basis(); } | ||||
|  |  | |||
|  | @ -228,33 +228,32 @@ class lp_bound_propagator { | |||
|         return lp().column_is_int(j); | ||||
|     } | ||||
| 
 | ||||
|     void explain_fixed_in_row(unsigned row, explanation& ex) const { | ||||
|     void explain_fixed_in_row(unsigned row, explanation& ex) { | ||||
|         TRACE("eq", tout << lp().get_row(row) << std::endl); | ||||
|         for (const auto& c : lp().get_row(row)) | ||||
|             if (lp().is_fixed(c.var())) | ||||
|                 explain_fixed_column(c.var(), ex); | ||||
|     } | ||||
| 
 | ||||
|     unsigned explain_fixed_in_row_and_get_base(unsigned row, explanation& ex) const { | ||||
|     unsigned explain_fixed_in_row_and_get_base(unsigned row, explanation& ex) { | ||||
|         unsigned base = UINT_MAX; | ||||
|         TRACE("eq", tout << lp().get_row(row) << std::endl); | ||||
|         for (const auto& c : lp().get_row(row)) { | ||||
|             if (lp().is_fixed(c.var())) { | ||||
|                 explain_fixed_column(c.var(), ex); | ||||
|             } else if (lp().is_base(c.var())) { | ||||
|             }  | ||||
|             else if (lp().is_base(c.var())) { | ||||
|                 base = c.var(); | ||||
|             } | ||||
|         } | ||||
|         return base; | ||||
|     } | ||||
| 
 | ||||
|     void explain_fixed_column(unsigned j, explanation& ex) const { | ||||
|     void explain_fixed_column(unsigned j, explanation& ex) { | ||||
|         SASSERT(column_is_fixed(j)); | ||||
|         constraint_index lc, uc; | ||||
|         lp().get_bound_constraint_witnesses_for_column(j, lc, uc); | ||||
|         ex.push_back(lc); | ||||
|         if (lc != uc) | ||||
|             ex.push_back(uc); | ||||
|         auto* deps = lp().get_bound_constraint_witnesses_for_column(j); | ||||
|         for (auto ci : lp().flatten(deps)) | ||||
|             ex.push_back(ci); | ||||
|     } | ||||
| #ifdef Z3DEBUG | ||||
|     bool all_fixed_in_row(unsigned row) const { | ||||
|  |  | |||
|  | @ -138,95 +138,98 @@ namespace lp { | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
| /**
 | ||||
|  * Return the number of base non-free variables depending on the column j, | ||||
|  * different from bj, | ||||
|  * but take the min with the (bound+1). | ||||
|  * This function is used to select the pivot variable. | ||||
| */ | ||||
|   unsigned get_num_of_not_free_basic_dependent_vars( | ||||
|       unsigned j, unsigned bound, unsigned bj) const { // consider looking at the signs here: todo
 | ||||
|     unsigned r = 0; | ||||
|     for (const auto &cc : this->m_A.m_columns[j]) { | ||||
|       unsigned basic_for_row = this->m_basis[cc.var()]; | ||||
|       if (basic_for_row == bj) | ||||
|         continue; | ||||
|          | ||||
|      // std::cout << this->m_A.m_rows[cc.var()] << std::endl;
 | ||||
|       if (this->m_column_types[basic_for_row] != column_type::free_column)          | ||||
|          if (r++ > bound) return r;       | ||||
|     } | ||||
|     return r; | ||||
|   } | ||||
|         int find_beneficial_entering_in_row_tableau_rows_bland_mode(int i, T &a_ent) { | ||||
|         int j = -1; | ||||
|         unsigned bj = this->m_basis[i]; | ||||
|         bool bj_needs_to_grow = needs_to_grow(bj); | ||||
|         for (const row_cell<T> &rc : this->m_A.m_rows[i]) { | ||||
|             if (rc.var() == bj) | ||||
|                 continue; | ||||
|             if (bj_needs_to_grow) { | ||||
|                 if (!monoid_can_decrease(rc)) | ||||
|                     continue; | ||||
|             } else { | ||||
|                 if (!monoid_can_increase(rc)) | ||||
|         /**
 | ||||
|          * Return the number of base non-free variables depending on the column j, | ||||
|          * different from bj, | ||||
|          * but take the min with the (bound+1). | ||||
|          * This function is used to select the pivot variable. | ||||
|          */ | ||||
|         unsigned get_num_of_not_free_basic_dependent_vars(unsigned j, unsigned bound, unsigned bj) const { | ||||
|             // consider looking at the signs here: todo
 | ||||
|             unsigned r = 0; | ||||
|             for (const auto &cc : this->m_A.m_columns[j]) { | ||||
|                 unsigned basic_for_row = this->m_basis[cc.var()]; | ||||
|                 if (basic_for_row == bj) | ||||
|                     continue; | ||||
| 
 | ||||
|                 // std::cout << this->m_A.m_rows[cc.var()] << std::endl;
 | ||||
|                 if (this->m_column_types[basic_for_row] != column_type::free_column) | ||||
|                     if (r++ > bound) return r; | ||||
|             } | ||||
|             if (rc.var() < static_cast<unsigned>(j)) { | ||||
|                 j = rc.var(); | ||||
|                 a_ent = rc.coeff(); | ||||
|             } | ||||
|         } | ||||
|         if (j == -1) | ||||
|             m_inf_row_index_for_tableau = i; | ||||
|         return j; | ||||
|     } | ||||
|         int find_beneficial_entering_tableau_rows(int i, T &a_ent) { | ||||
|         if (m_bland_mode_tableau) | ||||
|             return find_beneficial_entering_in_row_tableau_rows_bland_mode(i, a_ent); | ||||
|         // a short row produces short infeasibility explanation and benefits at
 | ||||
|         // least one pivot operation
 | ||||
|         int choice = -1; | ||||
|         int nchoices = 0; | ||||
|         unsigned min_non_free_so_far = -1; | ||||
|         unsigned best_col_sz = -1; | ||||
|         unsigned bj = this->m_basis[i]; | ||||
|         bool bj_needs_to_grow = needs_to_grow(bj); | ||||
|         for (unsigned k = 0; k < this->m_A.m_rows[i].size(); k++) { | ||||
|             const row_cell<T> &rc = this->m_A.m_rows[i][k]; | ||||
|             unsigned j = rc.var(); | ||||
|             if (j == bj) | ||||
|                 continue; | ||||
|             if (bj_needs_to_grow) { | ||||
|                 if (!monoid_can_decrease(rc)) | ||||
|                     continue; | ||||
|             } else { | ||||
|                 if (!monoid_can_increase(rc)) | ||||
|                     continue; | ||||
|             } | ||||
|             unsigned not_free = get_num_of_not_free_basic_dependent_vars(j, min_non_free_so_far, bj); | ||||
|             unsigned col_sz = this->m_A.m_columns[j].size(); | ||||
|             if (not_free < min_non_free_so_far || (not_free == min_non_free_so_far && col_sz < best_col_sz)) { | ||||
|                 min_non_free_so_far = not_free; | ||||
|                 best_col_sz = this->m_A.m_columns[j].size(); | ||||
|                 choice = k; | ||||
|                 nchoices = 1; | ||||
|             } else if (not_free == min_non_free_so_far && | ||||
|                        col_sz == best_col_sz) { | ||||
|                 if (this->m_settings.random_next(++nchoices) == 0) { | ||||
|                     choice = k; | ||||
|                 } | ||||
|             } | ||||
|             return r; | ||||
|         } | ||||
| 
 | ||||
|         if (choice == -1) { | ||||
|             m_inf_row_index_for_tableau = i; | ||||
|             return -1; | ||||
|         int find_beneficial_entering_in_row_tableau_rows_bland_mode(int i, T &a_ent) { | ||||
|             int j = -1; | ||||
|             unsigned bj = this->m_basis[i]; | ||||
|             bool bj_needs_to_grow = needs_to_grow(bj); | ||||
|             for (const row_cell<T> &rc : this->m_A.m_rows[i]) { | ||||
|                 if (rc.var() == bj) | ||||
|                     continue; | ||||
|                 if (bj_needs_to_grow) { | ||||
|                     if (!monoid_can_decrease(rc)) | ||||
|                         continue; | ||||
|                 }  | ||||
|                 else { | ||||
|                     if (!monoid_can_increase(rc)) | ||||
|                         continue; | ||||
|                 } | ||||
|                 if (rc.var() < static_cast<unsigned>(j)) { | ||||
|                     j = rc.var(); | ||||
|                     a_ent = rc.coeff(); | ||||
|                 } | ||||
|             } | ||||
|             if (j == -1) | ||||
|                 m_inf_row_index_for_tableau = i; | ||||
|             return j; | ||||
|         } | ||||
| 
 | ||||
|         int find_beneficial_entering_tableau_rows(int i, T &a_ent) { | ||||
|             if (m_bland_mode_tableau) | ||||
|             return find_beneficial_entering_in_row_tableau_rows_bland_mode(i, a_ent); | ||||
|             // a short row produces short infeasibility explanation and benefits at
 | ||||
|             // least one pivot operation
 | ||||
|             int choice = -1; | ||||
|             int nchoices = 0; | ||||
|             unsigned min_non_free_so_far = -1; | ||||
|             unsigned best_col_sz = -1; | ||||
|             unsigned bj = this->m_basis[i]; | ||||
|             bool bj_needs_to_grow = needs_to_grow(bj); | ||||
|             for (unsigned k = 0; k < this->m_A.m_rows[i].size(); k++) { | ||||
|                 const row_cell<T> &rc = this->m_A.m_rows[i][k]; | ||||
|                 unsigned j = rc.var(); | ||||
|                 if (j == bj) | ||||
|                     continue; | ||||
|                 if (bj_needs_to_grow) { | ||||
|                     if (!monoid_can_decrease(rc)) | ||||
|                         continue; | ||||
|                 } else { | ||||
|                     if (!monoid_can_increase(rc)) | ||||
|                         continue; | ||||
|                 } | ||||
|                 unsigned not_free = get_num_of_not_free_basic_dependent_vars(j, min_non_free_so_far, bj); | ||||
|                 unsigned col_sz = this->m_A.m_columns[j].size(); | ||||
|                 if (not_free < min_non_free_so_far || (not_free == min_non_free_so_far && col_sz < best_col_sz)) { | ||||
|                     min_non_free_so_far = not_free; | ||||
|                     best_col_sz = this->m_A.m_columns[j].size(); | ||||
|                     choice = k; | ||||
|                     nchoices = 1; | ||||
|                 }  | ||||
|                 else if (not_free == min_non_free_so_far && | ||||
|                        col_sz == best_col_sz) { | ||||
|                     if (this->m_settings.random_next(++nchoices) == 0)  | ||||
|                         choice = k;                     | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (choice == -1) { | ||||
|                 m_inf_row_index_for_tableau = i; | ||||
|                 return -1; | ||||
|             } | ||||
|             const row_cell<T> &rc = this->m_A.m_rows[i][choice]; | ||||
|             a_ent = rc.coeff(); | ||||
|             return rc.var(); | ||||
|         } | ||||
|         const row_cell<T> &rc = this->m_A.m_rows[i][choice]; | ||||
|         a_ent = rc.coeff(); | ||||
|         return rc.var(); | ||||
|     } | ||||
| 
 | ||||
|     bool try_jump_to_another_bound_on_entering(unsigned entering, const X &theta, X &t, bool &unlimited); | ||||
| 
 | ||||
|  |  | |||
|  | @ -22,6 +22,8 @@ Revision History: | |||
| #include <sstream> | ||||
| #include <limits.h> | ||||
| #include "util/debug.h" | ||||
| #include "util/dependency.h" | ||||
| 
 | ||||
| namespace nla { | ||||
|     class core; | ||||
| } | ||||
|  | @ -36,6 +38,7 @@ typedef unsigned lpvar; | |||
| const lpvar null_lpvar = UINT_MAX; | ||||
| const constraint_index null_ci = UINT_MAX; | ||||
| 
 | ||||
| 
 | ||||
| class column_index { | ||||
|     unsigned m_index; | ||||
|     friend class lar_solver; | ||||
|  |  | |||
|  | @ -149,22 +149,22 @@ namespace nla { | |||
|     } | ||||
| 
 | ||||
|     void monomial_bounds::var2interval(lpvar v, scoped_dep_interval& i) { | ||||
|         lp::constraint_index ci; | ||||
|         u_dependency* d = nullptr; | ||||
|         rational bound; | ||||
|         bool is_strict; | ||||
|         if (c().has_lower_bound(v, ci, bound, is_strict)) { | ||||
|         if (c().has_lower_bound(v, d, bound, is_strict)) { | ||||
|             dep.set_lower_is_open(i, is_strict); | ||||
|             dep.set_lower(i, bound); | ||||
|             dep.set_lower_dep(i, dep.mk_leaf(ci)); | ||||
|             dep.set_lower_dep(i, d); | ||||
|             dep.set_lower_is_inf(i, false); | ||||
|         } | ||||
|         else { | ||||
|             dep.set_lower_is_inf(i, true); | ||||
|         } | ||||
|         if (c().has_upper_bound(v, ci, bound, is_strict)) { | ||||
|         if (c().has_upper_bound(v, d, bound, is_strict)) { | ||||
|             dep.set_upper_is_open(i, is_strict); | ||||
|             dep.set_upper(i, bound); | ||||
|             dep.set_upper_dep(i, dep.mk_leaf(ci));             | ||||
|             dep.set_upper_dep(i, d);             | ||||
|             dep.set_upper_is_inf(i, false); | ||||
|         } | ||||
|         else { | ||||
|  |  | |||
|  | @ -60,11 +60,9 @@ unsigned common::random() { | |||
| } | ||||
| 
 | ||||
| void common::add_deps_of_fixed(lpvar j, u_dependency*& dep) { | ||||
|     unsigned lc, uc; | ||||
|     auto& dep_manager = c().m_intervals.get_dep_intervals().dep_manager(); | ||||
|     c().m_lar_solver.get_bound_constraint_witnesses_for_column(j, lc, uc); | ||||
|     dep = dep_manager.mk_join(dep, dep_manager.mk_leaf(lc)); | ||||
|     dep = dep_manager.mk_join(dep, dep_manager.mk_leaf(uc));                     | ||||
|     auto& dm = c().lra.dep_manager();   | ||||
|     auto* deps = c().lra.get_bound_constraint_witnesses_for_column(j); | ||||
|     dep = dm.mk_join(dep, deps);                | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -73,7 +71,7 @@ nex * common::nexvar(const rational & coeff, lpvar j, nex_creator& cn, u_depende | |||
|     SASSERT(!coeff.is_zero()); | ||||
|     if (c().params().arith_nl_horner_subs_fixed() == 1 && c().var_is_fixed(j)) { | ||||
|         add_deps_of_fixed(j, dep); | ||||
|         return cn.mk_scalar(coeff * c().m_lar_solver.column_lower_bound(j).x); | ||||
|         return cn.mk_scalar(coeff * c().lra.column_lower_bound(j).x); | ||||
|     } | ||||
|     if (c().params().arith_nl_horner_subs_fixed() == 2 && c().var_is_fixed_to_zero(j)) { | ||||
|         add_deps_of_fixed(j, dep); | ||||
|  | @ -91,7 +89,7 @@ nex * common::nexvar(const rational & coeff, lpvar j, nex_creator& cn, u_depende | |||
|     for (lpvar k : m.vars()) { | ||||
|         if (c().params().arith_nl_horner_subs_fixed() == 1 && c().var_is_fixed(k)) { | ||||
|             add_deps_of_fixed(k, dep); | ||||
|             mf *= c().m_lar_solver.column_lower_bound(k).x; | ||||
|             mf *= c().lra.column_lower_bound(k).x; | ||||
|         } else if (c().params().arith_nl_horner_subs_fixed() == 2 && | ||||
|                    c().var_is_fixed_to_zero(k)) { | ||||
|             dep = initial_dep; | ||||
|  |  | |||
|  | @ -80,21 +80,6 @@ struct common { | |||
|     bool check_monic(const monic&) const; | ||||
|     unsigned random(); | ||||
|     void add_deps_of_fixed(lpvar j, u_dependency*& dep); | ||||
|     class ci_value_manager { | ||||
|     public: | ||||
|         void inc_ref(lp::constraint_index const & v) { | ||||
|         } | ||||
| 
 | ||||
|         void dec_ref(lp::constraint_index const & v) { | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     struct u_dependency_config { | ||||
|         typedef ci_value_manager        value_manager; | ||||
|         typedef region  allocator; | ||||
|         static const bool ref_count = false; | ||||
|         typedef lp::constraint_index value; | ||||
|     }; | ||||
|          | ||||
|     nex* nexvar(const rational& coeff, lpvar j, nex_creator&, u_dependency*&); | ||||
|     template <typename T> | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ typedef lp::lar_term term; | |||
| 
 | ||||
| core::core(lp::lar_solver& s, params_ref const& p, reslimit & lim) : | ||||
|     m_evars(), | ||||
|     m_lar_solver(s), | ||||
|     lra(s), | ||||
|     m_reslim(lim), | ||||
|     m_params(p), | ||||
|     m_tangents(this), | ||||
|  | @ -69,7 +69,7 @@ lp::lar_term core::subs_terms_to_columns(const lp::lar_term& t) const { | |||
|     for (lp::lar_term::ival p : t) { | ||||
|         lpvar j = p.column(); | ||||
|         if (lp::tv::is_term(j)) | ||||
|             j = m_lar_solver.map_term_index_to_column_index(j); | ||||
|             j = lra.map_term_index_to_column_index(j); | ||||
|         r.add_monomial(p.coeff(), j); | ||||
|     } | ||||
|     return r; | ||||
|  | @ -133,7 +133,7 @@ void core::add_monic(lpvar v, unsigned sz, lpvar const* vs) { | |||
|     for (unsigned i = 0; i < sz; i++) { | ||||
|         lpvar j = vs[i]; | ||||
|         if (lp::tv::is_term(j)) | ||||
|             j = m_lar_solver.map_term_index_to_column_index(j); | ||||
|             j = lra.map_term_index_to_column_index(j); | ||||
|         m_add_buffer[i] = j; | ||||
|     } | ||||
|     m_emons.add(v, m_add_buffer); | ||||
|  | @ -154,7 +154,7 @@ void core::pop(unsigned n) { | |||
| rational core::product_value(const monic& m) const { | ||||
|     rational r(1); | ||||
|     for (auto j : m.vars()) { | ||||
|         r *= m_lar_solver.get_column_value(j).x; | ||||
|         r *= lra.get_column_value(j).x; | ||||
|     } | ||||
|     return r; | ||||
| } | ||||
|  | @ -167,10 +167,10 @@ bool core::check_monic(const monic& m) const { | |||
|     if (!is_relevant(m.var())) | ||||
|         return true; | ||||
| #endif | ||||
|     if (m_lar_solver.column_is_int(m.var()) && !m_lar_solver.get_column_value(m.var()).is_int()) | ||||
|     if (lra.column_is_int(m.var()) && !lra.get_column_value(m.var()).is_int()) | ||||
|         return true; | ||||
|      | ||||
|     bool ret = product_value(m) == m_lar_solver.get_column_value(m.var()).x;  | ||||
|     bool ret = product_value(m) == lra.get_column_value(m.var()).x;  | ||||
|     CTRACE("nla_solver_check_monic", !ret, print_monic(m, tout) << '\n';); | ||||
|     return ret; | ||||
| } | ||||
|  | @ -182,7 +182,7 @@ std::ostream& core::print_product(const T & m, std::ostream& out) const { | |||
|     for (lpvar v : m) { | ||||
|         if (!first) out << "*"; else first = false; | ||||
|         if (lp_settings().print_external_var_name()) | ||||
|             out << "(" << m_lar_solver.get_variable_name(v) << "=" << val(v) << ")"; | ||||
|             out << "(" << lra.get_variable_name(v) << "=" << val(v) << ")"; | ||||
|         else | ||||
|             out << "(j" << v << " = " << val(v) << ")"; | ||||
|              | ||||
|  | @ -228,7 +228,7 @@ std::ostream & core::print_factor_with_vars(const factor& f, std::ostream& out) | |||
| 
 | ||||
| std::ostream& core::print_monic(const monic& m, std::ostream& out) const { | ||||
|     if (lp_settings().print_external_var_name()) | ||||
|         out << "([" << m.var() << "] = " << m_lar_solver.get_variable_name(m.var()) << " = " << val(m.var()) << " = "; | ||||
|         out << "([" << m.var() << "] = " << lra.get_variable_name(m.var()) << " = " << val(m.var()) << " = "; | ||||
|     else  | ||||
|         out << "(j" << m.var() << " = " << val(m.var()) << " = "; | ||||
|     print_product(m.vars(), out) << ")\n"; | ||||
|  | @ -271,7 +271,7 @@ std::ostream& core::print_explanation(const lp::explanation& exp, std::ostream& | |||
|     unsigned i = 0; | ||||
|     for (auto p : exp) { | ||||
|         out << "(" << p.ci() << ")"; | ||||
|         m_lar_solver.constraints().display(out, [this](lpvar j) { return var_str(j);}, p.ci()); | ||||
|         lra.constraints().display(out, [this](lpvar j) { return var_str(j);}, p.ci()); | ||||
|         if (++i < exp.size()) | ||||
|             out << "      "; | ||||
|     } | ||||
|  | @ -316,21 +316,20 @@ bool core::explain_lower_bound(const lp::lar_term& t, const rational& rs, lp::ex | |||
| bool core::explain_coeff_lower_bound(const lp::lar_term::ival& p, rational& bound, lp::explanation& e) const { | ||||
|     const rational& a = p.coeff(); | ||||
|     SASSERT(!a.is_zero()); | ||||
|     unsigned c; // the index for the lower or the upper bound
 | ||||
|     if (a.is_pos()) { | ||||
|         unsigned c = m_lar_solver.get_column_lower_bound_witness(p.column()); | ||||
|         if (c + 1 == 0) | ||||
|         auto* dep = lra.get_column_lower_bound_witness(p.column()); | ||||
|         if (!dep) | ||||
|             return false; | ||||
|         bound = a * m_lar_solver.get_lower_bound(p.column()).x; | ||||
|         e.push_back(c); | ||||
|         bound = a * lra.get_lower_bound(p.column()).x; | ||||
|         lra.push_explanation(dep, e); | ||||
|         return true; | ||||
|     } | ||||
|     // a.is_neg()
 | ||||
|     c = m_lar_solver.get_column_upper_bound_witness(p.column()); | ||||
|     if (c + 1 == 0) | ||||
|     auto* dep = lra.get_column_upper_bound_witness(p.column()); | ||||
|     if (!dep) | ||||
|         return false; | ||||
|     bound = a * m_lar_solver.get_upper_bound(p.column()).x; | ||||
|     e.push_back(c); | ||||
|     bound = a * lra.get_upper_bound(p.column()).x; | ||||
|     lra.push_explanation(dep, e); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
|  | @ -338,21 +337,20 @@ bool core::explain_coeff_upper_bound(const lp::lar_term::ival& p, rational& boun | |||
|     const rational& a = p.coeff(); | ||||
|     lpvar j = p.column(); | ||||
|     SASSERT(!a.is_zero()); | ||||
|     unsigned c; // the index for the lower or the upper bound
 | ||||
|     if (a.is_neg()) { | ||||
|         unsigned c = m_lar_solver.get_column_lower_bound_witness(j); | ||||
|         if (c + 1 == 0) | ||||
|         auto *dep = lra.get_column_lower_bound_witness(j); | ||||
|         if (!dep) | ||||
|             return false; | ||||
|         bound = a * m_lar_solver.get_lower_bound(j).x; | ||||
|         e.push_back(c); | ||||
|         bound = a * lra.get_lower_bound(j).x; | ||||
|         lra.push_explanation(dep, e); | ||||
|         return true; | ||||
|     } | ||||
|     // a.is_pos()
 | ||||
|     c = m_lar_solver.get_column_upper_bound_witness(j); | ||||
|     if (c + 1 == 0) | ||||
|     auto* dep = lra.get_column_upper_bound_witness(j); | ||||
|     if (!dep) | ||||
|         return false; | ||||
|     bound = a * m_lar_solver.get_upper_bound(j).x; | ||||
|     e.push_back(c); | ||||
|     bound = a * lra.get_upper_bound(j).x; | ||||
|     lra.push_explanation(dep, e); | ||||
|     return true; | ||||
| } | ||||
|      | ||||
|  | @ -413,12 +411,12 @@ bool core::explain_by_equiv(const lp::lar_term& t, lp::explanation& e) const { | |||
|         return false; | ||||
|              | ||||
|     m_evars.explain(signed_var(i, false), signed_var(j, sign), e); | ||||
|     TRACE("nla_solver", tout << "explained :"; m_lar_solver.print_term_as_indices(t, tout);); | ||||
|     TRACE("nla_solver", tout << "explained :"; lra.print_term_as_indices(t, tout);); | ||||
|     return true;             | ||||
| } | ||||
| 
 | ||||
| void core::mk_ineq_no_expl_check(new_lemma& lemma, lp::lar_term& t, llc cmp, const rational& rs) { | ||||
|     TRACE("nla_solver_details", m_lar_solver.print_term_as_indices(t, tout << "t = ");); | ||||
|     TRACE("nla_solver_details", lra.print_term_as_indices(t, tout << "t = ");); | ||||
|     lemma |= ineq(cmp, t, rs); | ||||
|     CTRACE("nla_solver", ineq_holds(ineq(cmp, t, rs)), print_ineq(ineq(cmp, t, rs), tout) << "\n";); | ||||
|     SASSERT(!ineq_holds(ineq(cmp, t, rs))); | ||||
|  | @ -485,18 +483,18 @@ int core::vars_sign(const svector<lpvar>& v) { | |||
| } | ||||
|     | ||||
| bool core::has_upper_bound(lpvar j) const { | ||||
|     return m_lar_solver.column_has_upper_bound(j); | ||||
|     return lra.column_has_upper_bound(j); | ||||
| }  | ||||
| 
 | ||||
| bool core::has_lower_bound(lpvar j) const { | ||||
|     return m_lar_solver.column_has_lower_bound(j); | ||||
|     return lra.column_has_lower_bound(j); | ||||
| }  | ||||
| const rational& core::get_upper_bound(unsigned j) const { | ||||
|     return m_lar_solver.get_upper_bound(j).x; | ||||
|     return lra.get_upper_bound(j).x; | ||||
| } | ||||
| 
 | ||||
| const rational& core::get_lower_bound(unsigned j) const { | ||||
|     return m_lar_solver.get_lower_bound(j).x; | ||||
|     return lra.get_lower_bound(j).x; | ||||
| }     | ||||
|      | ||||
| bool core::zero_is_an_inner_point_of_bounds(lpvar j) const { | ||||
|  | @ -540,26 +538,26 @@ bool core::sign_contradiction(const monic& m) const { | |||
| 
 | ||||
| bool core::var_is_fixed_to_zero(lpvar j) const { | ||||
|     return  | ||||
|         m_lar_solver.column_is_fixed(j) && | ||||
|         m_lar_solver.get_lower_bound(j) == lp::zero_of_type<lp::impq>(); | ||||
|         lra.column_is_fixed(j) && | ||||
|         lra.get_lower_bound(j) == lp::zero_of_type<lp::impq>(); | ||||
| } | ||||
| bool core::var_is_fixed_to_val(lpvar j, const rational& v) const { | ||||
|     return  | ||||
|         m_lar_solver.column_is_fixed(j) && | ||||
|         m_lar_solver.get_lower_bound(j) == lp::impq(v); | ||||
|         lra.column_is_fixed(j) && | ||||
|         lra.get_lower_bound(j) == lp::impq(v); | ||||
| } | ||||
| 
 | ||||
| bool core::var_is_fixed(lpvar j) const { | ||||
|     return m_lar_solver.column_is_fixed(j); | ||||
|     return lra.column_is_fixed(j); | ||||
| } | ||||
| 
 | ||||
| bool core::var_is_free(lpvar j) const { | ||||
|     return m_lar_solver.column_is_free(j); | ||||
|     return lra.column_is_free(j); | ||||
| } | ||||
| 
 | ||||
|      | ||||
| std::ostream & core::print_ineq(const ineq & in, std::ostream & out) const { | ||||
|     m_lar_solver.print_term_as_indices(in.term(), out); | ||||
|     lra.print_term_as_indices(in.term(), out); | ||||
|     out << " " << lconstraint_kind_string(in.cmp()) << " " << in.rs(); | ||||
|     return out; | ||||
| } | ||||
|  | @ -569,14 +567,14 @@ std::ostream & core::print_var(lpvar j, std::ostream & out) const { | |||
|         print_monic(m_emons[j], out); | ||||
|     } | ||||
|          | ||||
|     m_lar_solver.print_column_info(j, out); | ||||
|     lra.print_column_info(j, out); | ||||
|     signed_var jr = m_evars.find(j); | ||||
|     out << "root="; | ||||
|     if (jr.sign()) { | ||||
|         out << "-"; | ||||
|     } | ||||
|          | ||||
|     out << m_lar_solver.get_variable_name(jr.var()) << "\n"; | ||||
|     out << lra.get_variable_name(jr.var()) << "\n"; | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
|  | @ -643,11 +641,11 @@ void core::trace_print_monic_and_factorization(const monic& rm, const factorizat | |||
| 
 | ||||
| 
 | ||||
| bool core::var_has_positive_lower_bound(lpvar j) const { | ||||
|     return m_lar_solver.column_has_lower_bound(j) && m_lar_solver.get_lower_bound(j) > lp::zero_of_type<lp::impq>(); | ||||
|     return lra.column_has_lower_bound(j) && lra.get_lower_bound(j) > lp::zero_of_type<lp::impq>(); | ||||
| } | ||||
| 
 | ||||
| bool core::var_has_negative_upper_bound(lpvar j) const { | ||||
|     return m_lar_solver.column_has_upper_bound(j) && m_lar_solver.get_upper_bound(j) < lp::zero_of_type<lp::impq>(); | ||||
|     return lra.column_has_upper_bound(j) && lra.get_upper_bound(j) < lp::zero_of_type<lp::impq>(); | ||||
| } | ||||
|      | ||||
| bool core::var_is_separated_from_zero(lpvar j) const { | ||||
|  | @ -684,10 +682,10 @@ template bool core::mon_has_zero<unsigned_vector>(const unsigned_vector& product | |||
| 
 | ||||
| 
 | ||||
| lp::lp_settings& core::lp_settings() { | ||||
|     return m_lar_solver.settings(); | ||||
|     return lra.settings(); | ||||
| } | ||||
| const lp::lp_settings& core::lp_settings() const { | ||||
|     return m_lar_solver.settings(); | ||||
|     return lra.settings(); | ||||
| } | ||||
|      | ||||
| unsigned core::random() { return lp_settings().random_next(); } | ||||
|  | @ -695,7 +693,7 @@ unsigned core::random() { return lp_settings().random_next(); } | |||
| 
 | ||||
| // we look for octagon constraints here, with a left part  +-x +- y 
 | ||||
| void core::collect_equivs() { | ||||
|     const lp::lar_solver& s = m_lar_solver; | ||||
|     const lp::lar_solver& s = lra; | ||||
| 
 | ||||
|     for (unsigned i = 0; i < s.terms().size(); i++) { | ||||
|         if (!s.term_is_used_as_row(i)) | ||||
|  | @ -737,7 +735,7 @@ bool core::is_octagon_term(const lp::lar_term& t, bool & sign, lpvar& i, lpvar & | |||
|     return true; | ||||
| } | ||||
|      | ||||
| void core::add_equivalence_maybe(const lp::lar_term *t, lpci c0, lpci c1) { | ||||
| void core::add_equivalence_maybe(const lp::lar_term* t, u_dependency* c0, u_dependency* c1) { | ||||
|     bool sign; | ||||
|     lpvar i, j; | ||||
|     if (!is_octagon_term(*t, sign, i, j)) | ||||
|  | @ -867,7 +865,7 @@ std::unordered_set<lpvar> core::collect_vars(const lemma& l) const { | |||
|         } | ||||
|     } | ||||
|     for (auto p : l.expl()) { | ||||
|         const auto& c = m_lar_solver.constraints()[p.ci()]; | ||||
|         const auto& c = lra.constraints()[p.ci()]; | ||||
|         for (const auto& r : c.coeffs()) { | ||||
|             insert_j(r.second); | ||||
|         } | ||||
|  | @ -1126,8 +1124,8 @@ new_lemma& new_lemma::explain_equiv(lpvar a, lpvar b) { | |||
| 
 | ||||
| new_lemma& new_lemma::explain_var_separated_from_zero(lpvar j) { | ||||
|     SASSERT(c.var_is_separated_from_zero(j)); | ||||
|     if (c.m_lar_solver.column_has_upper_bound(j) &&  | ||||
|         (c.m_lar_solver.get_upper_bound(j)< lp::zero_of_type<lp::impq>()))  | ||||
|     if (c.lra.column_has_upper_bound(j) &&  | ||||
|         (c.lra.get_upper_bound(j)< lp::zero_of_type<lp::impq>()))  | ||||
|         explain_existing_upper_bound(j); | ||||
|     else  | ||||
|         explain_existing_lower_bound(j); | ||||
|  | @ -1137,7 +1135,7 @@ new_lemma& new_lemma::explain_var_separated_from_zero(lpvar j) { | |||
| new_lemma& new_lemma::explain_existing_lower_bound(lpvar j) { | ||||
|     SASSERT(c.has_lower_bound(j)); | ||||
|     lp::explanation ex; | ||||
|     ex.push_back(c.m_lar_solver.get_column_lower_bound_witness(j)); | ||||
|     c.lra.push_explanation(c.lra.get_column_lower_bound_witness(j), ex); | ||||
|     *this &= ex; | ||||
|     TRACE("nla_solver", tout << j << ": " << *this << "\n";); | ||||
|     return *this; | ||||
|  | @ -1146,7 +1144,7 @@ new_lemma& new_lemma::explain_existing_lower_bound(lpvar j) { | |||
| new_lemma& new_lemma::explain_existing_upper_bound(lpvar j) { | ||||
|     SASSERT(c.has_upper_bound(j)); | ||||
|     lp::explanation ex; | ||||
|     ex.push_back(c.m_lar_solver.get_column_upper_bound_witness(j)); | ||||
|     c.lra.push_explanation(c.lra.get_column_upper_bound_witness(j), ex); | ||||
|     *this &= ex; | ||||
|     return *this; | ||||
| } | ||||
|  | @ -1156,7 +1154,7 @@ std::ostream& new_lemma::display(std::ostream & out) const { | |||
| 
 | ||||
|     for (auto p : lemma.expl()) { | ||||
|         out << "(" << p.ci() << ") "; | ||||
|         c.m_lar_solver.constraints().display(out, [this](lpvar j) { return c.var_str(j);}, p.ci()); | ||||
|         c.lra.constraints().display(out, [this](lpvar j) { return c.var_str(j);}, p.ci()); | ||||
|     } | ||||
|     out << " ==> "; | ||||
|     if (lemma.ineqs().empty()) { | ||||
|  | @ -1304,7 +1302,7 @@ bool core::has_real(const monic& m) const { | |||
| bool core::is_patch_blocked(lpvar u, const lp::impq& ival) const { | ||||
|     TRACE("nla_solver", tout << "u = " << u << '\n';); | ||||
|     if (m_cautious_patching && | ||||
|         (!m_lar_solver.inside_bounds(u, ival) || (var_is_int(u) && ival.is_int() == false))) { | ||||
|         (!lra.inside_bounds(u, ival) || (var_is_int(u) && ival.is_int() == false))) { | ||||
|         TRACE("nla_solver", tout << "u = " << u << " blocked, for feas or integr\n";); | ||||
|         return true; // block
 | ||||
|     } | ||||
|  | @ -1335,7 +1333,7 @@ bool core::is_patch_blocked(lpvar u, const lp::impq& ival) const { | |||
| bool core::try_to_patch(const rational& v) { | ||||
|     auto is_blocked = [this](lpvar u, const lp::impq& iv)  { return is_patch_blocked(u, iv); }; | ||||
|     auto change_report = [this](lpvar u) { update_to_refine_of_var(u); }; | ||||
|     return m_lar_solver.try_to_patch(m_patched_var, v, is_blocked, change_report); | ||||
|     return lra.try_to_patch(m_patched_var, v, is_blocked, change_report); | ||||
| } | ||||
| 
 | ||||
| bool in_power(const svector<lpvar>& vs, unsigned l) { | ||||
|  | @ -1344,7 +1342,7 @@ bool in_power(const svector<lpvar>& vs, unsigned l) { | |||
| } | ||||
| 
 | ||||
| bool core::to_refine_is_correct() const { | ||||
|     for (unsigned j = 0; j < m_lar_solver.number_of_vars(); j++) { | ||||
|     for (unsigned j = 0; j < lra.number_of_vars(); j++) { | ||||
|         if (!is_monic_var(j)) continue; | ||||
|         bool valid = check_monic(emons()[j]); | ||||
|         if (valid == m_to_refine.contains(j)) { | ||||
|  | @ -1436,17 +1434,17 @@ void core::patch_monomials() { | |||
|     NOT_IMPLEMENTED_YET(); | ||||
|     m_cautious_patching = false;  | ||||
|     patch_monomials_on_to_refine(); | ||||
|     m_lar_solver.push(); | ||||
|     lra.push(); | ||||
|     save_tableau(); | ||||
|     constrain_nl_in_tableau(); | ||||
|     if (solve_tableau() && integrality_holds()) { | ||||
|         m_lar_solver.pop(1); | ||||
|         lra.pop(1); | ||||
|     } else { | ||||
|         m_lar_solver.pop(); | ||||
|         lra.pop(); | ||||
|         restore_tableau(); | ||||
|         m_lar_solver.clear_inf_heap(); | ||||
|         lra.clear_inf_heap(); | ||||
|     } | ||||
|     SASSERT(m_lar_solver.ax_is_correct()); | ||||
|     SASSERT(lra.ax_is_correct()); | ||||
| } | ||||
| 
 | ||||
| void core::constrain_nl_in_tableau() { | ||||
|  | @ -1523,12 +1521,12 @@ void core::add_bounds() { | |||
| lbool core::check(vector<ineq>& lits, vector<lemma>& l_vec) { | ||||
|     lp_settings().stats().m_nla_calls++; | ||||
|     TRACE("nla_solver", tout << "calls = " << lp_settings().stats().m_nla_calls << "\n";); | ||||
|     m_lar_solver.get_rid_of_inf_eps(); | ||||
|     lra.get_rid_of_inf_eps(); | ||||
|     m_lemma_vec =  &l_vec; | ||||
|     m_literal_vec = &lits; | ||||
|     if (!(m_lar_solver.get_status() == lp::lp_status::OPTIMAL ||  | ||||
|           m_lar_solver.get_status() == lp::lp_status::FEASIBLE)) { | ||||
|         TRACE("nla_solver", tout << "unknown because of the m_lar_solver.m_status = " << m_lar_solver.get_status() << "\n";); | ||||
| 
 | ||||
|     if (!(lra.get_status() == lp::lp_status::OPTIMAL ||  | ||||
|           lra.get_status() == lp::lp_status::FEASIBLE)) { | ||||
|         TRACE("nla_solver", tout << "unknown because of the lra.m_status = " << lra.get_status() << "\n";); | ||||
|         return l_undef; | ||||
|     } | ||||
| 
 | ||||
|  | @ -1549,6 +1547,9 @@ lbool core::check(vector<ineq>& lits, vector<lemma>& l_vec) { | |||
|      | ||||
|     if (no_effect()) | ||||
|         m_monomial_bounds(); | ||||
| 
 | ||||
|     if (l_vec.empty() && !done() && improve_bounds()) | ||||
|         return l_false; | ||||
|      | ||||
|     { | ||||
|         std::function<void(void)> check1 = [&]() { if (no_effect() && run_horner) m_horner.horner_lemmas(); }; | ||||
|  | @ -1657,21 +1658,21 @@ bool core::no_lemmas_hold() const { | |||
|      | ||||
| lbool core::test_check(vector<lemma>& l) { | ||||
|     vector<ineq> lits; | ||||
|     m_lar_solver.set_status(lp::lp_status::OPTIMAL); | ||||
|     lra.set_status(lp::lp_status::OPTIMAL); | ||||
|     return check(lits, l); | ||||
| } | ||||
| 
 | ||||
| std::ostream& core::print_terms(std::ostream& out) const { | ||||
|     for (unsigned i = 0; i< m_lar_solver.terms().size(); i++) { | ||||
|     for (unsigned i = 0; i< lra.terms().size(); i++) { | ||||
|         unsigned ext = lp::tv::mask_term(i); | ||||
|         if (!m_lar_solver.var_is_registered(ext)) { | ||||
|         if (!lra.var_is_registered(ext)) { | ||||
|             out << "term is not registered\n"; | ||||
|             continue; | ||||
|         } | ||||
|          | ||||
|         const lp::lar_term & t = *m_lar_solver.terms()[i]; | ||||
|         const lp::lar_term & t = *lra.terms()[i]; | ||||
|         out << "term:"; print_term(t, out) << std::endl;         | ||||
|         lpvar j = m_lar_solver.external_to_local(ext); | ||||
|         lpvar j = lra.external_to_local(ext); | ||||
|         print_var(j, out); | ||||
|     } | ||||
|     return out; | ||||
|  | @ -1699,7 +1700,7 @@ std::ostream& core::print_term( const lp::lar_term& t, std::ostream& out) const | |||
| 
 | ||||
| std::unordered_set<lpvar> core::get_vars_of_expr_with_opening_terms(const nex *e ) { | ||||
|     auto ret = get_vars_of_expr(e); | ||||
|     auto & ls = m_lar_solver; | ||||
|     auto & ls = lra; | ||||
|     svector<lpvar> added; | ||||
|     for (auto j : ret) { | ||||
|         added.push_back(j); | ||||
|  | @ -1707,7 +1708,7 @@ std::unordered_set<lpvar> core::get_vars_of_expr_with_opening_terms(const nex *e | |||
|     for (unsigned i = 0; i < added.size(); ++i) { | ||||
|         lpvar j = added[i]; | ||||
|         if (ls.column_corresponds_to_term(j)) { | ||||
|             const auto& t = m_lar_solver.get_term(lp::tv::raw(ls.local_to_external(j))); | ||||
|             const auto& t = lra.get_term(lp::tv::raw(ls.local_to_external(j))); | ||||
|             for (auto p : t) { | ||||
|                 if (ret.find(p.column()) == ret.end()) { | ||||
|                     added.push_back(p.column()); | ||||
|  | @ -1727,7 +1728,7 @@ bool core::is_nl_var(lpvar j) const { | |||
| 
 | ||||
| unsigned core::get_var_weight(lpvar j) const { | ||||
|     unsigned k; | ||||
|     switch (m_lar_solver.get_column_type(j)) { | ||||
|     switch (lra.get_column_type(j)) { | ||||
| 
 | ||||
|     case lp::column_type::fixed: | ||||
|         k = 0; | ||||
|  | @ -1756,7 +1757,7 @@ unsigned core::get_var_weight(lpvar j) const { | |||
| 
 | ||||
| 
 | ||||
| void core::set_active_vars_weights(nex_creator& nc) { | ||||
|     nc.set_number_of_vars(m_lar_solver.column_count()); | ||||
|     nc.set_number_of_vars(lra.column_count()); | ||||
|     for (lpvar j : active_var_set())  | ||||
|         nc.set_var_weight(j, get_var_weight(j)); | ||||
| } | ||||
|  | @ -1766,8 +1767,8 @@ bool core::influences_nl_var(lpvar j) const { | |||
|         j = lp::tv::unmask_term(j); | ||||
|     if (is_nl_var(j)) | ||||
|         return true; | ||||
|     for (const auto & c : m_lar_solver.A_r().m_columns[j]) { | ||||
|         lpvar basic_in_row = m_lar_solver.r_basis()[c.var()]; | ||||
|     for (const auto & c : lra.A_r().m_columns[j]) { | ||||
|         lpvar basic_in_row = lra.r_basis()[c.var()]; | ||||
|         if (is_nl_var(basic_in_row)) | ||||
|             return true;         | ||||
|     } | ||||
|  | @ -1784,9 +1785,32 @@ void core::set_use_nra_model(bool m) { | |||
| void core::collect_statistics(::statistics & st) { | ||||
|     st.update("arith-nla-explanations", m_stats.m_nla_explanations); | ||||
|     st.update("arith-nla-lemmas", m_stats.m_nla_lemmas); | ||||
|     st.update("arith-nra-calls", m_stats.m_nra_calls);     | ||||
|     st.update("arith-nra-calls", m_stats.m_nra_calls);    | ||||
|     st.update("arith-bounds-improvements", m_stats.m_bounds_improvements); | ||||
| } | ||||
| 
 | ||||
| bool core::improve_bounds() { | ||||
|     return false; | ||||
| 
 | ||||
|     uint_set seen; | ||||
|     bool bounds_improved = false; | ||||
|     auto insert = [&](lpvar v) { | ||||
|         if (seen.contains(v)) | ||||
|             return; | ||||
|         seen.insert(v); | ||||
|         if (lra.improve_bound(v, false)) | ||||
|             bounds_improved = true, m_stats.m_bounds_improvements++; | ||||
|         if (lra.improve_bound(v, true)) | ||||
|             bounds_improved = true, m_stats.m_bounds_improvements++; | ||||
|     }; | ||||
|     for (auto & m : m_emons) { | ||||
|         insert(m.var()); | ||||
|         for (auto v : m.vars()) | ||||
|             insert(v); | ||||
|     } | ||||
|     return bounds_improved; | ||||
| } | ||||
|      | ||||
| 
 | ||||
| } // end of nla
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -64,6 +64,7 @@ class core { | |||
|         unsigned m_nla_explanations; | ||||
|         unsigned m_nla_lemmas; | ||||
|         unsigned m_nra_calls; | ||||
|         unsigned m_bounds_improvements; | ||||
|         stats() { reset(); } | ||||
|         void reset() { | ||||
|             memset(this, 0, sizeof(*this)); | ||||
|  | @ -79,7 +80,7 @@ class core { | |||
| 
 | ||||
|     var_eqs<emonics>         m_evars; | ||||
| 
 | ||||
|     lp::lar_solver&          m_lar_solver; | ||||
|     lp::lar_solver&          lra; | ||||
|     reslimit&                m_reslim; | ||||
|     smt_params_helper        m_params; | ||||
|     std::function<bool(lpvar)> m_relevant; | ||||
|  | @ -111,6 +112,9 @@ class core { | |||
| 
 | ||||
|     void check_weighted(unsigned sz, std::pair<unsigned, std::function<void(void)>>* checks); | ||||
|     void add_bounds(); | ||||
|     // try to improve bounds for variables in monomials.
 | ||||
|     bool improve_bounds(); | ||||
| 
 | ||||
| public:     | ||||
|     // constructor
 | ||||
|     core(lp::lar_solver& s, params_ref const& p, reslimit&); | ||||
|  | @ -143,13 +147,13 @@ public: | |||
|     bool ineq_holds(const ineq& n) const; | ||||
|     bool lemma_holds(const lemma& l) const; | ||||
|     bool is_monic_var(lpvar j) const { return m_emons.is_monic_var(j); } | ||||
|     const rational& val(lpvar j) const { return m_lar_solver.get_column_value(j).x; } | ||||
|     const rational& val(lpvar j) const { return lra.get_column_value(j).x; } | ||||
| 
 | ||||
|     const rational& var_val(const monic& m) const { return m_lar_solver.get_column_value(m.var()).x; } | ||||
|     const rational& var_val(const monic& m) const { return lra.get_column_value(m.var()).x; } | ||||
| 
 | ||||
|     rational mul_val(const monic& m) const {  | ||||
|         rational r(1); | ||||
|         for (lpvar v : m.vars()) r *= m_lar_solver.get_column_value(v).x; | ||||
|         for (lpvar v : m.vars()) r *= lra.get_column_value(v).x; | ||||
|         return r; | ||||
|     } | ||||
| 
 | ||||
|  | @ -288,16 +292,16 @@ public: | |||
|     } | ||||
|     const rational& get_upper_bound(unsigned j) const; | ||||
|     const rational& get_lower_bound(unsigned j) const;     | ||||
|     bool has_lower_bound(lp::var_index var, lp::constraint_index& ci, lp::mpq& value, bool& is_strict) const {  | ||||
|         return m_lar_solver.has_lower_bound(var, ci, value, is_strict);  | ||||
|     bool has_lower_bound(lp::var_index var, u_dependency*& ci, lp::mpq& value, bool& is_strict) const {  | ||||
|         return lra.has_lower_bound(var, ci, value, is_strict);  | ||||
|     } | ||||
|     bool has_upper_bound(lp::var_index var, lp::constraint_index& ci, lp::mpq& value, bool& is_strict) const { | ||||
|         return m_lar_solver.has_upper_bound(var, ci, value, is_strict); | ||||
|     bool has_upper_bound(lp::var_index var, u_dependency*& ci, lp::mpq& value, bool& is_strict) const { | ||||
|         return lra.has_upper_bound(var, ci, value, is_strict); | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     bool zero_is_an_inner_point_of_bounds(lpvar j) const;     | ||||
|     bool var_is_int(lpvar j) const { return m_lar_solver.column_is_int(j); } | ||||
|     bool var_is_int(lpvar j) const { return lra.column_is_int(j); } | ||||
|     int rat_sign(const monic& m) const; | ||||
|     inline int rat_sign(lpvar j) const { return nla::rat_sign(val(j)); } | ||||
| 
 | ||||
|  | @ -339,7 +343,7 @@ public: | |||
| 
 | ||||
|     bool is_octagon_term(const lp::lar_term& t, bool & sign, lpvar& i, lpvar &j) const; | ||||
|      | ||||
|     void add_equivalence_maybe(const lp::lar_term *t, lpci c0, lpci c1); | ||||
|     void add_equivalence_maybe(const lp::lar_term* t, u_dependency* c0, u_dependency* c1); | ||||
| 
 | ||||
|     void init_vars_equivalence(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,11 +14,10 @@ | |||
| #include "math/lp/explanation.h" | ||||
| 
 | ||||
| namespace nla { | ||||
| typedef lp::constraint_index lpci; | ||||
| typedef lp::lconstraint_kind llc; | ||||
| typedef lp::constraint_index     lpci; | ||||
| typedef lp::explanation          expl_set; | ||||
| typedef lp::var_index            lpvar; | ||||
|     typedef lp::constraint_index lpci; | ||||
|     typedef lp::lconstraint_kind llc; | ||||
|     typedef lp::explanation          expl_set; | ||||
|     typedef lp::var_index            lpvar; | ||||
| 
 | ||||
| struct from_index_dummy{}; | ||||
| class signed_var { | ||||
|  |  | |||
|  | @ -22,9 +22,9 @@ namespace nla { | |||
| 
 | ||||
|     grobner::grobner(core* c): | ||||
|         common(c), | ||||
|         m_pdd_manager(m_core.m_lar_solver.number_of_vars()), | ||||
|         m_solver(m_core.m_reslim, m_pdd_manager), | ||||
|         m_lar_solver(m_core.m_lar_solver), | ||||
|         m_pdd_manager(m_core.lra.number_of_vars()), | ||||
|         m_solver(m_core.m_reslim, m_core.lra.dep_manager(), m_pdd_manager), | ||||
|         lra(m_core.lra), | ||||
|         m_quota(m_core.params().arith_nl_gr_q()) | ||||
|     {} | ||||
| 
 | ||||
|  | @ -211,12 +211,12 @@ namespace nla { | |||
|             TRACE("grobner", | ||||
|                   tout << "base vars: "; | ||||
|                   for (lpvar j : c().active_var_set()) | ||||
|                       if (m_lar_solver.is_base(j)) | ||||
|                       if (lra.is_base(j)) | ||||
|                           tout << "j" << j << " "; | ||||
|                   tout << "\n"); | ||||
|             for (lpvar j : c().active_var_set()) { | ||||
|                 if (m_lar_solver.is_base(j)) | ||||
|                     add_row(m_lar_solver.basic2row(j)); | ||||
|                 if (lra.is_base(j)) | ||||
|                     add_row(lra.basic2row(j)); | ||||
|                  | ||||
|                 if (c().is_monic_var(j) && c().var_is_fixed(j)) | ||||
|                     add_fixed_monic(j); | ||||
|  | @ -267,12 +267,12 @@ namespace nla { | |||
|             } | ||||
|         }   | ||||
|    | ||||
|         for (unsigned j = 0; j < m_lar_solver.number_of_vars(); ++j) { | ||||
|             if (m_lar_solver.column_has_lower_bound(j) || m_lar_solver.column_has_upper_bound(j)) { | ||||
|         for (unsigned j = 0; j < lra.number_of_vars(); ++j) { | ||||
|             if (lra.column_has_lower_bound(j) || lra.column_has_upper_bound(j)) { | ||||
|                 out << j << ": ["; | ||||
|                 if (m_lar_solver.column_has_lower_bound(j)) out << m_lar_solver.get_lower_bound(j); | ||||
|                 if (lra.column_has_lower_bound(j)) out << lra.get_lower_bound(j); | ||||
|                 out << ".."; | ||||
|                 if (m_lar_solver.column_has_upper_bound(j)) out << m_lar_solver.get_upper_bound(j); | ||||
|                 if (lra.column_has_upper_bound(j)) out << lra.get_upper_bound(j); | ||||
|                 out << "]\n"; | ||||
|             } | ||||
|         }               | ||||
|  | @ -343,14 +343,14 @@ namespace nla { | |||
| 
 | ||||
|         if (c().var_is_fixed(j)) | ||||
|             return; | ||||
|         const auto& matrix = m_lar_solver.A_r(); | ||||
|         const auto& matrix = lra.A_r(); | ||||
|         for (auto & s : matrix.m_columns[j]) { | ||||
|             unsigned row = s.var(); | ||||
|             if (m_rows.contains(row)) | ||||
|                 continue; | ||||
|             m_rows.insert(row); | ||||
|             unsigned k = m_lar_solver.get_base_column_in_row(row); | ||||
|             if (m_lar_solver.column_is_free(k) && k != j) | ||||
|             unsigned k = lra.get_base_column_in_row(row); | ||||
|             if (lra.column_is_free(k) && k != j) | ||||
|                 continue; | ||||
|             CTRACE("grobner", matrix.m_rows[row].size() > c().params().arith_nl_grobner_row_length_limit(), | ||||
|                    tout << "ignore the row " << row << " with the size " << matrix.m_rows[row].size() << "\n";);  | ||||
|  | @ -362,11 +362,10 @@ namespace nla { | |||
|     } | ||||
| 
 | ||||
|     const rational& grobner::val_of_fixed_var_with_deps(lpvar j, u_dependency*& dep) { | ||||
|         unsigned lc, uc; | ||||
|         m_lar_solver.get_bound_constraint_witnesses_for_column(j, lc, uc); | ||||
|         dep = c().m_intervals.mk_join(dep, c().m_intervals.mk_leaf(lc)); | ||||
|         dep = c().m_intervals.mk_join(dep, c().m_intervals.mk_leaf(uc)); | ||||
|         return m_lar_solver.column_lower_bound(j).x; | ||||
|         auto* d = lra.get_bound_constraint_witnesses_for_column(j); | ||||
|         if (d) | ||||
|             dep = c().m_intervals.mk_join(dep, d); | ||||
|         return lra.column_lower_bound(j).x; | ||||
|     } | ||||
| 
 | ||||
|     dd::pdd grobner::pdd_expr(const rational& coeff, lpvar j, u_dependency*& dep) { | ||||
|  | @ -415,7 +414,7 @@ namespace nla { | |||
|             SASSERT(r.hi().is_val()); | ||||
|             v = r.var(); | ||||
|             rational val = r.hi().val(); | ||||
|             switch (m_lar_solver.get_column_type(v)) { | ||||
|             switch (lra.get_column_type(v)) { | ||||
|             case lp::column_type::lower_bound: | ||||
|                 if (val > 0) num_lo++, lo = v, lc = val; else num_hi++, hi = v, hc = val; | ||||
|                 break; | ||||
|  | @ -508,7 +507,7 @@ namespace nla { | |||
| 
 | ||||
| 
 | ||||
|     void grobner::display_matrix_of_m_rows(std::ostream & out) const { | ||||
|         const auto& matrix = m_lar_solver.A_r(); | ||||
|         const auto& matrix = lra.A_r(); | ||||
|         out << m_rows.size() << " rows" << "\n"; | ||||
|         out << "the matrix\n";           | ||||
|         for (const auto & r : matrix.m_rows)  | ||||
|  | @ -516,7 +515,7 @@ namespace nla { | |||
|     } | ||||
|      | ||||
|     void grobner::set_level2var() { | ||||
|         unsigned n = m_lar_solver.column_count(); | ||||
|         unsigned n = lra.column_count(); | ||||
|         unsigned_vector sorted_vars(n), weighted_vars(n); | ||||
|         for (unsigned j = 0; j < n; j++) { | ||||
|             sorted_vars[j] = j; | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ namespace nla { | |||
|     class grobner : common { | ||||
|         dd::pdd_manager          m_pdd_manager; | ||||
|         dd::solver               m_solver; | ||||
|         lp::lar_solver&          m_lar_solver; | ||||
|         lp::lar_solver&          lra; | ||||
|         indexed_uint_set         m_rows; | ||||
|         unsigned                 m_quota = 0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,6 +4,11 @@ | |||
| #include "util/mpq.h" | ||||
| 
 | ||||
| namespace nla { | ||||
| 
 | ||||
| intervals::intervals(core* c, reslimit& lim): | ||||
|     m_dep_intervals(c->lra.dep_manager(), lim), | ||||
|     m_core(c) {} | ||||
| 
 | ||||
| typedef enum dep_intervals::with_deps_t e_with_deps; | ||||
| 
 | ||||
| const nex* intervals::get_inf_interval_child(const nex_sum& e) const { | ||||
|  | @ -173,7 +178,7 @@ lp::lar_term intervals::expression_to_normalized_term(const nex_sum* e, rational | |||
| // where m_terms[k] corresponds to the returned lpvar
 | ||||
| lpvar intervals::find_term_column(const lp::lar_term & norm_t, rational& a) const { | ||||
|     std::pair<rational, lpvar> a_j; | ||||
|     if (m_core->m_lar_solver.fetch_normalized_term_column(norm_t, a_j)) { | ||||
|     if (m_core->lra.fetch_normalized_term_column(norm_t, a_j)) { | ||||
|         a /= a_j.first; | ||||
|         return a_j.second; | ||||
|     } | ||||
|  | @ -206,19 +211,10 @@ void intervals::set_zero_interval_deps_for_mult(interval& a) { | |||
|     a.m_upper_dep = a.m_lower_dep; | ||||
| } | ||||
| 
 | ||||
| u_dependency *intervals::mk_dep(lp::constraint_index ci) { | ||||
|     return m_dep_intervals.mk_leaf(ci); | ||||
| } | ||||
| 
 | ||||
| u_dependency *intervals::mk_dep(const lp::explanation& expl) { | ||||
| u_dependency* intervals::mk_dep(const lp::explanation& expl) { | ||||
|     u_dependency * r = nullptr; | ||||
|     for (auto p : expl) { | ||||
|         if (r == nullptr) { | ||||
|             r = m_dep_intervals.mk_leaf(p.ci()); | ||||
|         } else { | ||||
|             r = m_dep_intervals.mk_join(r, m_dep_intervals.mk_leaf(p.ci())); | ||||
|         } | ||||
|     } | ||||
|     for (auto p : expl)  | ||||
|         r = m_dep_intervals.mk_join(r, m_dep_intervals.mk_leaf(p.ci())); | ||||
|     return r; | ||||
| } | ||||
| 
 | ||||
|  | @ -249,25 +245,25 @@ std::ostream& intervals::display(std::ostream& out, const interval& i) const { | |||
| template <e_with_deps wd> | ||||
| void intervals::set_var_interval(lpvar v, interval& b) { | ||||
|     TRACE("nla_intervals_details", m_core->print_var(v, tout) << "\n";); | ||||
|     lp::constraint_index ci; | ||||
|     u_dependency* dep = nullptr; | ||||
|     rational val; | ||||
|     bool is_strict; | ||||
|     if (ls().has_lower_bound(v, ci, val, is_strict)) { | ||||
|     if (ls().has_lower_bound(v, dep, val, is_strict)) { | ||||
|         m_dep_intervals.set_lower(b, val); | ||||
|         m_dep_intervals.set_lower_is_open(b, is_strict); | ||||
|         m_dep_intervals.set_lower_is_inf(b, false); | ||||
|         if (wd == e_with_deps::with_deps) b.m_lower_dep = mk_dep(ci); | ||||
|         if (wd == e_with_deps::with_deps) b.m_lower_dep = dep; | ||||
|     } | ||||
|     else { | ||||
|         m_dep_intervals.set_lower_is_open(b, true); | ||||
|         m_dep_intervals.set_lower_is_inf(b, true); | ||||
|         if (wd == e_with_deps::with_deps) b.m_lower_dep = nullptr; | ||||
|     } | ||||
|     if (ls().has_upper_bound(v, ci, val, is_strict)) { | ||||
|     if (ls().has_upper_bound(v, dep, val, is_strict)) { | ||||
|         m_dep_intervals.set_upper(b, val); | ||||
|         m_dep_intervals.set_upper_is_open(b, is_strict); | ||||
|         m_dep_intervals.set_upper_is_inf(b, false); | ||||
|         if (wd == e_with_deps::with_deps) b.m_upper_dep = mk_dep(ci); | ||||
|         if (wd == e_with_deps::with_deps) b.m_upper_dep = dep; | ||||
|     } | ||||
|     else { | ||||
|         m_dep_intervals.set_upper_is_open(b, true); | ||||
|  | @ -303,7 +299,7 @@ bool intervals::interval_from_term(const nex& e, scoped_dep_interval& i) { | |||
|     m_dep_intervals.set<wd>(i, bi); | ||||
| 
 | ||||
|     TRACE("nla_intervals", | ||||
|           m_core->m_lar_solver.print_column_info(j, tout) << "\n"; | ||||
|           m_core->lra.print_column_info(j, tout) << "\n"; | ||||
|           tout << "a=" << a << ", b=" << b << "\n"; | ||||
|           tout << e << ", interval = "; display(tout, i);); | ||||
|     return true; | ||||
|  | @ -476,9 +472,9 @@ bool intervals::interval_of_expr(const nex* e, unsigned p, scoped_dep_interval& | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| lp::lar_solver& intervals::ls() { return m_core->m_lar_solver; } | ||||
| lp::lar_solver& intervals::ls() { return m_core->lra; } | ||||
| 
 | ||||
| const lp::lar_solver& intervals::ls() const { return m_core->m_lar_solver; } | ||||
| const lp::lar_solver& intervals::ls() const { return m_core->lra; } | ||||
| 
 | ||||
| 
 | ||||
| } // end of nla namespace
 | ||||
|  |  | |||
|  | @ -25,16 +25,13 @@ class intervals { | |||
| public: | ||||
|     typedef dep_intervals::interval interval; | ||||
| private: | ||||
|     u_dependency* mk_dep(lp::constraint_index ci); | ||||
|     u_dependency* mk_dep(lp::explanation const&); | ||||
|     lp::lar_solver& ls(); | ||||
|     const lp::lar_solver& ls() const; | ||||
| public: | ||||
| 
 | ||||
|     intervals(core* c, reslimit& lim) : | ||||
|         m_dep_intervals(lim), | ||||
|         m_core(c) | ||||
|     {} | ||||
|     intervals(core* c, reslimit& lim); | ||||
| 
 | ||||
|     dep_intervals& get_dep_intervals() { return m_dep_intervals; } | ||||
|     u_dependency* mk_join(u_dependency* a, u_dependency* b) { return m_dep_intervals.mk_join(a, b); } | ||||
|     u_dependency* mk_leaf(lp::constraint_index ci) { return m_dep_intervals.mk_leaf(ci); } | ||||
|  |  | |||
|  | @ -186,7 +186,7 @@ struct solver::imp { | |||
|         for (auto const& eq : eqs) | ||||
|             add_eq(eq); | ||||
|         for (auto const& [v, w] : m_lp2nl) { | ||||
|             auto& ls = m_nla_core.m_lar_solver; | ||||
|             auto& ls = m_nla_core.lra; | ||||
|             if (ls.column_has_lower_bound(v)) | ||||
|                 add_lb(ls.get_lower_bound(v), w); | ||||
|             if (ls.column_has_upper_bound(v)) | ||||
|  | @ -209,7 +209,7 @@ struct solver::imp { | |||
|         IF_VERBOSE(0, verbose_stream() << "check-nra " << r << "\n"; | ||||
|                    m_nlsat->display(verbose_stream()); | ||||
|                    for (auto const& [v, w] : m_lp2nl) { | ||||
|                        auto& ls = m_nla_core.m_lar_solver; | ||||
|                        auto& ls = m_nla_core.lra; | ||||
|                        if (ls.column_has_lower_bound(v)) | ||||
|                            verbose_stream() << w << " >= " << ls.get_lower_bound(v) << "\n"; | ||||
|                        if (ls.column_has_upper_bound(v)) | ||||
|  |  | |||
|  | @ -1,25 +1,19 @@ | |||
| /*++
 | ||||
| Copyright (c) 2017 Microsoft Corporation | ||||
| 
 | ||||
| Module Name: | ||||
| 
 | ||||
|     <name> | ||||
| 
 | ||||
| Abstract: | ||||
| 
 | ||||
|     <abstract> | ||||
|     justifications for upper or lower bounds | ||||
| 
 | ||||
| Author: | ||||
| 
 | ||||
|     Lev Nachmanson (levnach) | ||||
| 
 | ||||
| Revision History: | ||||
| 
 | ||||
| 
 | ||||
| --*/ | ||||
| 
 | ||||
| #pragma once | ||||
| #include "util/vector.h" | ||||
| #include "util/dependency.h" | ||||
| #include <string> | ||||
| #include <algorithm> | ||||
| #include <utility> | ||||
|  | @ -48,14 +42,20 @@ inline bool compare(const std::pair<mpq, var_index> & a, const std::pair<mpq, va | |||
| } | ||||
| 
 | ||||
| class ul_pair { | ||||
|     constraint_index m_lower_bound_witness; | ||||
|     constraint_index m_upper_bound_witness; | ||||
|     bool             m_associated_with_row;   | ||||
|     u_dependency* m_lower_bound_witness = nullptr; | ||||
|     u_dependency* m_upper_bound_witness = nullptr; | ||||
|     bool                   m_associated_with_row = false;   | ||||
| public: | ||||
|     constraint_index& lower_bound_witness() {return m_lower_bound_witness;} | ||||
|     constraint_index lower_bound_witness() const {return m_lower_bound_witness;} | ||||
|     constraint_index& upper_bound_witness() { return m_upper_bound_witness;} | ||||
|     constraint_index upper_bound_witness() const {return m_upper_bound_witness;} | ||||
|     // TODO - seems more straight-forward to just expose ul_pair as a struct with direct access to attributes.
 | ||||
|      | ||||
|     u_dependency*& lower_bound_witness() { return m_lower_bound_witness; } | ||||
|     u_dependency* lower_bound_witness() const { return m_lower_bound_witness; } | ||||
|     u_dependency*& upper_bound_witness() { return m_upper_bound_witness; } | ||||
|     u_dependency* upper_bound_witness() const { return m_upper_bound_witness; } | ||||
| 
 | ||||
|     // equality is used by stackedvector operations.
 | ||||
|     // this appears to be a low level reason
 | ||||
|      | ||||
|     bool operator!=(const ul_pair & p) const { | ||||
|         return !(*this == p); | ||||
|     } | ||||
|  | @ -66,14 +66,9 @@ public: | |||
|             m_associated_with_row == p.m_associated_with_row; | ||||
|     } | ||||
|     // empty constructor
 | ||||
|     ul_pair() : | ||||
|         m_lower_bound_witness(UINT_MAX), | ||||
|         m_upper_bound_witness(UINT_MAX), | ||||
|         m_associated_with_row(false) {} | ||||
|     ul_pair() {} | ||||
| 
 | ||||
|     ul_pair(bool associated_with_row) : | ||||
|         m_lower_bound_witness(UINT_MAX), | ||||
|         m_upper_bound_witness(UINT_MAX), | ||||
|         m_associated_with_row(associated_with_row) {} | ||||
| 
 | ||||
|     bool associated_with_row() const { return m_associated_with_row; } | ||||
|  |  | |||
|  | @ -28,22 +28,24 @@ | |||
| namespace nla { | ||||
| 
 | ||||
| class eq_justification { | ||||
|     lpci m_cs[4]; | ||||
|     u_dependency* m_cs[4]; | ||||
| public: | ||||
|     eq_justification(std::initializer_list<lpci> cs) { | ||||
|     eq_justification(std::initializer_list<u_dependency*> cs) { | ||||
|         int i = 0; | ||||
|         for (lpci c: cs) { | ||||
|         for (auto c: cs) { | ||||
|             m_cs[i++] = c; | ||||
|         } | ||||
|         for (; i < 4; i++) { | ||||
|             m_cs[i] = -1; | ||||
|             m_cs[i] = nullptr; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void explain(lp::explanation& e) const { | ||||
|         for (lpci c : m_cs) | ||||
|             if (c + 1 != 0) // c != -1
 | ||||
|                 e.push_back(c); | ||||
|     u_dependency* const* begin() const { return m_cs; } | ||||
|     u_dependency* const* end() const { | ||||
|         unsigned i = 0; | ||||
|         for (; i < 4 && m_cs[i]; ++i) | ||||
|             ; | ||||
|         return m_cs + i; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
|  | @ -202,7 +204,7 @@ public: | |||
|         } | ||||
|          | ||||
|         for (eq_justification const& j : m_justtrail) { | ||||
|             j.explain(e); | ||||
|             explain_eq(j, e); | ||||
|         } | ||||
|         m_stats.m_num_explains += m_justtrail.size(); | ||||
|         m_stats.m_num_explain_calls++; | ||||
|  | @ -216,6 +218,17 @@ public: | |||
|         // IF_VERBOSE(2, verbose_stream() << (double)m_stats.m_num_explains / m_stats.m_num_explain_calls << "\n");
 | ||||
|     } | ||||
| 
 | ||||
|     void explain_eq(eq_justification const& eq, lp::explanation& e) const { | ||||
|         u_dependency_manager dm; | ||||
|         unsigned_vector deps; | ||||
|         for (auto* dep : eq) { | ||||
|             deps.reset(); | ||||
|             dm.linearize(dep, deps); | ||||
|             for (auto ci : deps) | ||||
|                 e.push_back(ci); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void explain_bfs(signed_var v1, signed_var v2, lp::explanation& e) const { | ||||
|         SASSERT(find(v1) == find(v2)); | ||||
|         if (v1 == v2) { | ||||
|  | @ -249,7 +262,7 @@ public: | |||
|         } | ||||
|          | ||||
|         while (head != 0) { | ||||
|             m_justtrail[head].explain(e); | ||||
|             explain_eq(m_justtrail[head], e); | ||||
|             head = m_todo[head].m_index; | ||||
|             ++m_stats.m_num_explains; | ||||
|         } | ||||
|  |  | |||
|  | @ -278,7 +278,6 @@ struct mbp_array_tg::impl { | |||
|         m_tg.get_terms(terms, false); | ||||
|         for (unsigned i = 0; i < terms.size(); i++) { | ||||
|             term = terms.get(i); | ||||
|             SASSERT(!m.is_distinct(term)); | ||||
|             if (m_seen.is_marked(term)) continue; | ||||
|             if (m_tg.is_cgr(term)) continue; | ||||
|             TRACE("mbp_tg", tout << "processing " << expr_ref(term, m);); | ||||
|  |  | |||
|  | @ -43,40 +43,105 @@ struct mbp_basic_tg::impl { | |||
|     void mark_seen(expr *t) { m_seen.mark(t); } | ||||
|     bool is_seen(expr *t) { return m_seen.is_marked(t); } | ||||
| 
 | ||||
|     //Split on all ite terms, irrespective of whether
 | ||||
|     //they contain variables/are c-ground
 | ||||
|     // Split on all ite terms, irrespective of whether
 | ||||
|     // they contain variables/are c-ground
 | ||||
|     bool apply() { | ||||
|         if (!m_use_mdl) return false; | ||||
|         expr *term, *c, *th, *el; | ||||
|         std::function<bool(expr *)> should_split, is_true, is_false; | ||||
|         if (!m_use_mdl) { | ||||
|             should_split = [&](expr *t) { return m_tg.has_val_in_class(t); }; | ||||
|             is_true = [&](expr *t) { | ||||
|                 return m_tg.has_val_in_class(t) && m_mdl.is_true(t); | ||||
|             }; | ||||
|             is_false = [&](expr *t) { | ||||
|                 return m_tg.has_val_in_class(t) && m_mdl.is_false(t); | ||||
|             }; | ||||
|         } else { | ||||
|             should_split = [](expr *t) { return true; }; | ||||
|             is_true = [&](expr *t) { return m_mdl.is_true(t); }; | ||||
|             is_false = [&](expr *t) { return m_mdl.is_false(t); }; | ||||
|         } | ||||
| 
 | ||||
|         expr *c, *th, *el; | ||||
|         expr_ref nterm(m); | ||||
|         bool progress = false; | ||||
|         TRACE("mbp_tg", tout << "Iterating over terms of tg";); | ||||
|         // Not resetting terms because get_terms calls resize on terms
 | ||||
|         m_tg.get_terms(terms, false); | ||||
|         for (unsigned i = 0; i < terms.size(); i++) { | ||||
|             term = terms.get(i); | ||||
|             // Unsupported operators
 | ||||
|             SASSERT(!m.is_and(term)); | ||||
|             SASSERT(!m.is_or(term)); | ||||
|             SASSERT(!m.is_distinct(term)); | ||||
|             SASSERT(!m.is_implies(term)); | ||||
| 
 | ||||
|         for (expr *term : terms) { | ||||
|             if (is_seen(term)) continue; | ||||
|             if (m.is_ite(term, c, th, el)) { | ||||
|             if (m.is_ite(term, c, th, el) && should_split(c)) { | ||||
|                 mark_seen(term); | ||||
|                 progress = true; | ||||
|                 if (m_mdl.is_true(c)) { | ||||
|                     m_tg.add_lit(c); | ||||
|                     m_tg.add_eq(term, th); | ||||
|                 } else { | ||||
|                     if (m.is_not(c)) | ||||
|                         nterm = to_app(c)->get_arg(0); | ||||
|                     else | ||||
|                         nterm = m.mk_not(c); | ||||
|                     nterm = mk_not(m, c); | ||||
|                     m_tg.add_lit(nterm); | ||||
|                     m_tg.add_eq(term, el); | ||||
|                 } | ||||
|                 continue; | ||||
|             } | ||||
|             if (m.is_implies(term, c, th)) { | ||||
|                 if (is_true(th) || is_false(c)) { | ||||
|                     mark_seen(term); | ||||
|                     progress = true; | ||||
|                     if (is_true(th)) | ||||
|                         m_tg.add_lit(th); | ||||
|                     else if (is_false(c)) | ||||
|                         m_tg.add_lit(c); | ||||
|                     m_tg.add_eq(term, m.mk_true()); | ||||
|                 } else if (is_true(c) && is_false(th)) { | ||||
|                     mark_seen(term); | ||||
|                     progress = true; | ||||
|                     m_tg.add_eq(term, m.mk_false()); | ||||
|                 } | ||||
|             } | ||||
|             if (m.is_or(term) || m.is_and(term)) { | ||||
|                 bool is_or = m.is_or(term); | ||||
|                 app *c = to_app(term); | ||||
|                 bool t = is_or ? any_of(*c, is_true) : all_of(*c, is_true); | ||||
|                 bool f = is_or ? all_of(*c, is_false) : all_of(*c, is_false); | ||||
|                 if (t || f) { | ||||
|                     mark_seen(term); | ||||
|                     progress = true; | ||||
|                     m_tg.add_eq(term, t ? m.mk_true() : m.mk_false()); | ||||
|                     if (f) { | ||||
|                         for (auto a : *c) { | ||||
|                             if (is_false(a)) { | ||||
|                                 m_tg.add_lit(mk_not(m, a)); | ||||
|                                 if (!is_or) break; | ||||
|                             } | ||||
|                         } | ||||
|                     } else { | ||||
|                         for (auto a : *c) { | ||||
|                             if (is_true(a)) { | ||||
|                                 m_tg.add_lit(a); | ||||
|                                 if (is_or) break; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (m_use_mdl && m.is_distinct(term)) { | ||||
|                 mark_seen(term); | ||||
|                 progress = true; | ||||
|                 bool eq = false; | ||||
|                 app *c = to_app(term); | ||||
|                 for (auto a1 : *c) { | ||||
|                     for (auto a2 : *c) { | ||||
|                         if (a1 == a2) continue; | ||||
|                         if (m_mdl.are_equal(a1, a2)) { | ||||
|                             m_tg.add_eq(a1, a2); | ||||
|                             eq = true; | ||||
|                             break; | ||||
|                         } else | ||||
|                             m_tg.add_deq(a1, a2); | ||||
|                     } | ||||
|                 } | ||||
|                 if (eq) | ||||
|                     m_tg.add_eq(term, m.mk_false()); | ||||
|                 else | ||||
|                     m_tg.add_eq(term, m.mk_true()); | ||||
|             } | ||||
|         } | ||||
|         return progress; | ||||
|  |  | |||
|  | @ -158,7 +158,6 @@ struct mbp_dt_tg::impl { | |||
|         m_tg.get_terms(terms, false); | ||||
|         for (unsigned i = 0; i < terms.size(); i++) { | ||||
|             term = terms.get(i); | ||||
|             SASSERT(!m.is_distinct(term)); | ||||
|             if (is_seen(term)) continue; | ||||
|             if (m_tg.is_cgr(term)) continue; | ||||
|             if (is_app(term) && | ||||
|  |  | |||
|  | @ -178,7 +178,7 @@ class mbp_qel::impl { | |||
| 
 | ||||
|         std::function<bool(expr *)> non_core = [&](expr *e) { | ||||
|             if (is_app(e) && is_partial_eq(to_app(e))) return true; | ||||
|             if (m.is_ite(e)) return true; | ||||
|             if (m.is_ite(e) || m.is_or(e) || m.is_implies(e) || m.is_and(e) || m.is_distinct(e)) return true; | ||||
|             return red_vars.is_marked(e); | ||||
|         }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,7 +42,8 @@ namespace sat { | |||
|              | ||||
|     void anf_simplifier::operator()() { | ||||
|         dd::pdd_manager m(20, dd::pdd_manager::semantics::mod2_e); | ||||
|         pdd_solver solver(s.rlimit(), m); | ||||
|         u_dependency_manager dm; | ||||
|         pdd_solver solver(s.rlimit(), dm, m); | ||||
|         report _report(*this); | ||||
|         configure_solver(solver); | ||||
|         clauses2anf(solver); | ||||
|  |  | |||
|  | @ -524,7 +524,7 @@ namespace arith { | |||
|         return all_divs_valid; | ||||
|     } | ||||
| 
 | ||||
|     void solver::fixed_var_eh(theory_var v, lp::constraint_index ci1, lp::constraint_index ci2, rational const& bound) { | ||||
|     void solver::fixed_var_eh(theory_var v, u_dependency* dep, rational const& bound) { | ||||
|         theory_var w = euf::null_theory_var; | ||||
|         enode* x = var2enode(v); | ||||
|         if (bound.is_zero())  | ||||
|  | @ -540,8 +540,8 @@ namespace arith { | |||
|             return; | ||||
|         reset_evidence(); | ||||
|         m_explanation.clear(); | ||||
|         consume(rational::one(), ci1); | ||||
|         consume(rational::one(), ci2); | ||||
|         for (auto ci : lp().flatten(dep)) | ||||
|             consume(rational::one(), ci); | ||||
|         ++m_stats.m_fixed_eqs; | ||||
|         auto* hint = explain_implied_eq(m_explanation, x, y); | ||||
|         auto* jst = euf::th_explain::propagate(*this, m_core, m_eqs, x, y, hint); | ||||
|  |  | |||
|  | @ -402,12 +402,13 @@ namespace arith { | |||
|     } | ||||
| 
 | ||||
|     void solver::propagate_eqs(lp::tv t, lp::constraint_index ci1, lp::lconstraint_kind k, api_bound& b, rational const& value) { | ||||
|         lp::constraint_index ci2; | ||||
|         if (k == lp::GE && set_lower_bound(t, ci1, value) && has_upper_bound(t.index(), ci2, value)) { | ||||
|             fixed_var_eh(b.get_var(), ci1, ci2, value); | ||||
|         u_dependency* dep; | ||||
|         auto& dm = lp().dep_manager(); | ||||
|         if (k == lp::GE && set_lower_bound(t, ci1, value) && has_upper_bound(t.index(), dep, value)) { | ||||
|             fixed_var_eh(b.get_var(), dm.mk_join(dm.mk_leaf(ci1), dep), value); | ||||
|         } | ||||
|         else if (k == lp::LE && set_upper_bound(t, ci1, value) && has_lower_bound(t.index(), ci2, value)) { | ||||
|             fixed_var_eh(b.get_var(), ci1, ci2, value); | ||||
|         else if (k == lp::LE && set_upper_bound(t, ci1, value) && has_lower_bound(t.index(), dep, value)) { | ||||
|             fixed_var_eh(b.get_var(), dm.mk_join(dm.mk_leaf(ci1), dep), value); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -433,11 +434,12 @@ namespace arith { | |||
|             // m_solver already tracks bounds on proper variables, but not on terms.
 | ||||
|             bool is_strict = false; | ||||
|             rational b; | ||||
|             u_dependency* dep = nullptr; | ||||
|             if (is_lower) { | ||||
|                 return lp().has_lower_bound(tv.id(), ci, b, is_strict) && !is_strict && b == v; | ||||
|                 return lp().has_lower_bound(tv.id(), dep, b, is_strict) && !is_strict && b == v; | ||||
|             } | ||||
|             else { | ||||
|                 return lp().has_upper_bound(tv.id(), ci, b, is_strict) && !is_strict && b == v; | ||||
|                 return lp().has_upper_bound(tv.id(), dep, b, is_strict) && !is_strict && b == v; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -692,7 +694,7 @@ namespace arith { | |||
| 
 | ||||
|     void solver::report_equality_of_fixed_vars(unsigned vi1, unsigned vi2) { | ||||
|         rational bound; | ||||
|         lp::constraint_index ci1, ci2, ci3, ci4; | ||||
|         u_dependency* ci1 = nullptr, *ci2 = nullptr, *ci3 = nullptr, *ci4 = nullptr; | ||||
|         theory_var v1 = lp().local_to_external(vi1); | ||||
|         theory_var v2 = lp().local_to_external(vi2); | ||||
|         TRACE("arith", tout << "fixed: " << mk_pp(var2expr(v1), m) << " " << mk_pp(var2expr(v2), m) << "\n";); | ||||
|  | @ -714,10 +716,10 @@ namespace arith { | |||
|         ++m_stats.m_fixed_eqs; | ||||
|         reset_evidence(); | ||||
|         m_explanation.clear(); | ||||
|         consume(rational::one(), ci1); | ||||
|         consume(rational::one(), ci2); | ||||
|         consume(rational::one(), ci3); | ||||
|         consume(rational::one(), ci4); | ||||
|         auto& dm = lp().dep_manager(); | ||||
|         auto* d = dm.mk_join(dm.mk_join(ci1, ci2), dm.mk_join(ci3, ci4)); | ||||
|         for (auto ci : lp().flatten(d)) | ||||
|             consume(rational::one(), ci); | ||||
|         enode* x = var2enode(v1); | ||||
|         enode* y = var2enode(v2); | ||||
|         auto* ex = explain_implied_eq(m_explanation, x, y); | ||||
|  | @ -729,26 +731,28 @@ namespace arith { | |||
|         return x == y || var2enode(x)->get_root() == var2enode(y)->get_root(); | ||||
|     } | ||||
| 
 | ||||
|     bool solver::has_upper_bound(lpvar vi, lp::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, false); } | ||||
|     bool solver::has_upper_bound(lpvar vi, u_dependency*& ci, rational const& bound) { return has_bound(vi, ci, bound, false); } | ||||
| 
 | ||||
|     bool solver::has_lower_bound(lpvar vi, lp::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, true); } | ||||
|     bool solver::has_lower_bound(lpvar vi, u_dependency*& ci, rational const& bound) { return has_bound(vi, ci, bound, true); } | ||||
| 
 | ||||
|     bool solver::has_bound(lpvar vi, lp::constraint_index& ci, rational const& bound, bool is_lower) { | ||||
|     bool solver::has_bound(lpvar vi, u_dependency*& dep, rational const& bound, bool is_lower) { | ||||
|         if (lp::tv::is_term(vi)) { | ||||
|             theory_var v = lp().local_to_external(vi); | ||||
|             rational val; | ||||
|             TRACE("arith", tout << lp().get_variable_name(vi) << " " << v << "\n";); | ||||
|             if (v != euf::null_theory_var && a.is_numeral(var2expr(v), val) && bound == val) { | ||||
|                 ci = UINT_MAX; | ||||
|                 dep = nullptr; | ||||
|                 return bound == val; | ||||
|             } | ||||
| 
 | ||||
|             auto& vec = is_lower ? m_lower_terms : m_upper_terms; | ||||
|             lpvar ti = lp::tv::unmask_term(vi); | ||||
|             if (vec.size() > ti) { | ||||
|                 constraint_bound& b = vec[ti]; | ||||
|                 ci = b.first; | ||||
|                 return ci != UINT_MAX && bound == b.second; | ||||
|                 auto& [ci, coeff] = vec[ti]; | ||||
|                 if (ci == UINT_MAX) | ||||
|                     return false; | ||||
|                 dep = lp().dep_manager().mk_leaf(ci); | ||||
|                 return bound == coeff; | ||||
|             } | ||||
|             else { | ||||
|                 return false; | ||||
|  | @ -758,10 +762,10 @@ namespace arith { | |||
|             bool is_strict = false; | ||||
|             rational b; | ||||
|             if (is_lower) { | ||||
|                 return lp().has_lower_bound(vi, ci, b, is_strict) && b == bound && !is_strict; | ||||
|                 return lp().has_lower_bound(vi, dep, b, is_strict) && b == bound && !is_strict; | ||||
|             } | ||||
|             else { | ||||
|                 return lp().has_upper_bound(vi, ci, b, is_strict) && b == bound && !is_strict; | ||||
|                 return lp().has_upper_bound(vi, dep, b, is_strict) && b == bound && !is_strict; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -360,7 +360,7 @@ namespace arith { | |||
|         void assert_idiv_mod_axioms(theory_var u, theory_var v, theory_var w, rational const& r); | ||||
|         api_bound* mk_var_bound(sat::literal lit, theory_var v, lp_api::bound_kind bk, rational const& bound); | ||||
|         lp::lconstraint_kind bound2constraint_kind(bool is_int, lp_api::bound_kind bk, bool is_true); | ||||
|         void fixed_var_eh(theory_var v1, lp::constraint_index ci1, lp::constraint_index ci2, rational const& bound); | ||||
|         void fixed_var_eh(theory_var v1, u_dependency* dep, rational const& bound); | ||||
|         bool set_upper_bound(lp::tv t, lp::constraint_index ci, rational const& v) { return set_bound(t, ci, v, false); } | ||||
|         bool set_lower_bound(lp::tv t, lp::constraint_index ci, rational const& v) { return set_bound(t, ci, v, true); } | ||||
|         bool set_bound(lp::tv tv, lp::constraint_index ci, rational const& v, bool is_lower); | ||||
|  | @ -413,9 +413,9 @@ namespace arith { | |||
|         nlsat::anum const& nl_value(theory_var v, scoped_anum& r) const; | ||||
| 
 | ||||
| 
 | ||||
|         bool has_bound(lpvar vi, lp::constraint_index& ci, rational const& bound, bool is_lower); | ||||
|         bool has_lower_bound(lpvar vi, lp::constraint_index& ci, rational const& bound); | ||||
|         bool has_upper_bound(lpvar vi, lp::constraint_index& ci, rational const& bound); | ||||
|         bool has_bound(lpvar vi, u_dependency*& ci, rational const& bound, bool is_lower); | ||||
|         bool has_lower_bound(lpvar vi, u_dependency*& ci, rational const& bound); | ||||
|         bool has_upper_bound(lpvar vi, u_dependency*& ci, rational const& bound); | ||||
| 
 | ||||
|         /*
 | ||||
|          * Facility to put a small box around integer variables used in branch and bounds. | ||||
|  |  | |||
|  | @ -67,6 +67,8 @@ namespace smt { | |||
|             m_ge(ge) { | ||||
|         } | ||||
| 
 | ||||
|         ~arith_eq_relevancy_eh() override {} | ||||
| 
 | ||||
|         void operator()(relevancy_propagator & rp) override { | ||||
|             if (!rp.is_relevant(m_n1)) | ||||
|                 return; | ||||
|  |  | |||
|  | @ -3565,7 +3565,6 @@ namespace smt { | |||
|         try { | ||||
|             internalize_assertions(); | ||||
|         } catch (cancel_exception&) { | ||||
|             VERIFY(resource_limits_exceeded()); | ||||
|             return l_undef; | ||||
|         } | ||||
|         expr_ref_vector theory_assumptions(m); | ||||
|  | @ -3637,7 +3636,6 @@ namespace smt { | |||
|                 TRACE("unsat_core_bug", tout << asms << '\n';); | ||||
|                 init_assumptions(asms); | ||||
|             } catch (cancel_exception&) { | ||||
|                 VERIFY(resource_limits_exceeded()); | ||||
|                 return l_undef; | ||||
|             } | ||||
|             TRACE("before_search", display(tout);); | ||||
|  | @ -3664,7 +3662,6 @@ namespace smt { | |||
|                 for (auto const& clause : clauses) if (!validate_assumptions(clause)) return l_undef; | ||||
|                 init_assumptions(asms); | ||||
|             } catch (cancel_exception&) { | ||||
|                 VERIFY(resource_limits_exceeded()); | ||||
|                 return l_undef; | ||||
|             } | ||||
|             for (auto const& clause : clauses) init_clause(clause); | ||||
|  |  | |||
|  | @ -123,7 +123,7 @@ namespace smt { | |||
|     } | ||||
|      | ||||
|     struct relevancy_propagator_imp : public relevancy_propagator { | ||||
|         unsigned                       m_qhead; | ||||
|         unsigned                       m_qhead = 0; | ||||
|         expr_ref_vector                m_relevant_exprs;  | ||||
|         uint_set                       m_is_relevant; | ||||
|         typedef list<relevancy_eh *>   relevancy_ehs; | ||||
|  | @ -144,14 +144,18 @@ namespace smt { | |||
|             unsigned m_trail_lim; | ||||
|         }; | ||||
|         svector<scope>                 m_scopes; | ||||
|         bool                           m_propagating; | ||||
|         bool                           m_propagating = false; | ||||
| 
 | ||||
|         relevancy_propagator_imp(context & ctx): | ||||
|             relevancy_propagator(ctx), m_qhead(0), m_relevant_exprs(ctx.get_manager()), | ||||
|             m_propagating(false) {} | ||||
|             relevancy_propagator(ctx), m_relevant_exprs(ctx.get_manager()) {} | ||||
| 
 | ||||
|         ~relevancy_propagator_imp() override { | ||||
|             undo_trail(0); | ||||
|             ast_manager & m = get_manager(); | ||||
|             unsigned i = m_trail.size(); | ||||
|             while (i != 0) { | ||||
|                 --i; | ||||
|                 m.dec_ref(m_trail[i].get_node()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         relevancy_ehs * get_handlers(expr * n) { | ||||
|  |  | |||
|  | @ -41,13 +41,14 @@ namespace smt { | |||
|         /**
 | ||||
|            \brief Fallback for the two previous methods. | ||||
|         */ | ||||
|         virtual void operator()(relevancy_propagator & rp) {} | ||||
|         virtual void operator()(relevancy_propagator & rp) = 0; | ||||
|     }; | ||||
| 
 | ||||
|     class simple_relevancy_eh : public relevancy_eh { | ||||
|         expr * m_target; | ||||
|     public: | ||||
|         simple_relevancy_eh(expr * t):m_target(t) {} | ||||
|         ~simple_relevancy_eh() override {} | ||||
|         void operator()(relevancy_propagator & rp) override; | ||||
|     }; | ||||
|      | ||||
|  | @ -60,6 +61,7 @@ namespace smt { | |||
|         expr * m_target; | ||||
|     public: | ||||
|         pair_relevancy_eh(expr * s1, expr * s2, expr * t):m_source1(s1), m_source2(s2), m_target(t) {} | ||||
|         ~pair_relevancy_eh() override {} | ||||
|         void operator()(relevancy_propagator & rp) override; | ||||
|     }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -546,7 +546,7 @@ namespace smt { | |||
| 
 | ||||
|         expr_ref def2(m.mk_app(f, args2.size(), args2.data()), m); | ||||
|         ctx.get_rewriter()(def2); | ||||
|         expr* def1 = mk_default(map); | ||||
|         expr_ref def1(mk_default(map), m); | ||||
|         ctx.internalize(def1, false); | ||||
|         ctx.internalize(def2, false); | ||||
|         return try_assign_eq(def1, def2); | ||||
|  | @ -561,7 +561,7 @@ namespace smt { | |||
|         SASSERT(is_const(cnst)); | ||||
|         TRACE("array", tout << mk_bounded_pp(cnst->get_expr(), m) << "\n";); | ||||
|         expr* val = cnst->get_arg(0)->get_expr(); | ||||
|         expr* def = mk_default(cnst->get_expr()); | ||||
|         expr_ref def(mk_default(cnst->get_expr()), m); | ||||
|         ctx.internalize(def, false); | ||||
|         return try_assign_eq(val, def); | ||||
|     } | ||||
|  | @ -598,7 +598,7 @@ namespace smt { | |||
|             return false; | ||||
|         m_stats.m_num_default_lambda_axiom++; | ||||
|         expr* e = arr->get_expr(); | ||||
|         expr* def = mk_default(e); | ||||
|         expr_ref def(mk_default(e), m); | ||||
|         quantifier* lam = m.is_lambda_def(arr->get_decl()); | ||||
|         TRACE("array", tout << mk_pp(lam, m) << "\n" << mk_pp(e, m) << "\n"); | ||||
|         expr_ref_vector args(m);        | ||||
|  |  | |||
|  | @ -2874,7 +2874,7 @@ public: | |||
|         lp::lar_term const& term = lp().get_term(ti); | ||||
|         for (auto const mono : term) { | ||||
|             auto wi = lp().column2tv(mono.column()); | ||||
|             lp::constraint_index ci; | ||||
|             u_dependency* ci = nullptr; | ||||
|             rational value; | ||||
|             bool is_strict; | ||||
|             if (wi.is_term()) { | ||||
|  | @ -2977,12 +2977,13 @@ public: | |||
|     vector<constraint_bound>        m_upper_terms; | ||||
| 
 | ||||
|     void propagate_eqs(lp::tv t, lp::constraint_index ci1, lp::lconstraint_kind k, api_bound& b, rational const& value) { | ||||
|         lp::constraint_index ci2; | ||||
|         u_dependency* ci2 = nullptr; | ||||
|         auto pair = [&]() { return lp().dep_manager().mk_join(lp().dep_manager().mk_leaf(ci1), ci2);  }; | ||||
|         if (k == lp::GE && set_lower_bound(t, ci1, value) && has_upper_bound(t.index(), ci2, value)) { | ||||
|             fixed_var_eh(b.get_var(), t, ci1, ci2, value); | ||||
|             fixed_var_eh(b.get_var(), t, pair(), value); | ||||
|         } | ||||
|         else if (k == lp::LE && set_upper_bound(t, ci1, value) && has_lower_bound(t.index(), ci2, value)) { | ||||
|             fixed_var_eh(b.get_var(), t, ci1, ci2, value); | ||||
|             fixed_var_eh(b.get_var(), t, pair(), value); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -3023,11 +3024,12 @@ public: | |||
|             // m_solver already tracks bounds on proper variables, but not on terms.
 | ||||
|             bool is_strict = false; | ||||
|             rational b; | ||||
|             u_dependency* dep = nullptr; | ||||
|             if (is_lower) { | ||||
|                 return lp().has_lower_bound(tv.id(), ci, b, is_strict) && !is_strict && b == v; | ||||
|                 return lp().has_lower_bound(tv.id(), dep, b, is_strict) && !is_strict && b == v; | ||||
|             } | ||||
|             else { | ||||
|                 return lp().has_upper_bound(tv.id(), ci, b, is_strict) && !is_strict && b == v; | ||||
|                 return lp().has_upper_bound(tv.id(), dep, b, is_strict) && !is_strict && b == v; | ||||
|             }             | ||||
|         } | ||||
|     } | ||||
|  | @ -3035,35 +3037,37 @@ public: | |||
|     bool var_has_bound(lpvar vi, bool is_lower) { | ||||
|         bool is_strict = false; | ||||
|         rational b; | ||||
|         lp::constraint_index ci; | ||||
|         u_dependency* dep; | ||||
|         if (is_lower) { | ||||
|             return lp().has_lower_bound(vi, ci, b, is_strict); | ||||
|             return lp().has_lower_bound(vi, dep, b, is_strict); | ||||
|         } | ||||
|         else { | ||||
|             return lp().has_upper_bound(vi, ci, b, is_strict); | ||||
|             return lp().has_upper_bound(vi, dep, b, is_strict); | ||||
|         }         | ||||
|     } | ||||
| 
 | ||||
|     bool has_upper_bound(lpvar vi, lp::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, false); } | ||||
|     bool has_upper_bound(lpvar vi, u_dependency*& ci, rational const& bound) { return has_bound(vi, ci, bound, false); } | ||||
| 
 | ||||
|     bool has_lower_bound(lpvar vi, lp::constraint_index& ci, rational const& bound) { return has_bound(vi, ci, bound, true); } | ||||
|     bool has_lower_bound(lpvar vi, u_dependency*& ci, rational const& bound) { return has_bound(vi, ci, bound, true); } | ||||
|         | ||||
|     bool has_bound(lpvar vi, lp::constraint_index& ci, rational const& bound, bool is_lower) { | ||||
|     bool has_bound(lpvar vi, u_dependency*& dep, rational const& bound, bool is_lower) { | ||||
|         if (lp::tv::is_term(vi)) { | ||||
|             theory_var v = lp().local_to_external(vi); | ||||
|             rational val; | ||||
|             TRACE("arith", tout << lp().get_variable_name(vi) << " " << v << "\n";); | ||||
|             if (v != null_theory_var && a.is_numeral(get_owner(v), val) && bound == val) { | ||||
|                 ci = UINT_MAX; | ||||
|                 dep = nullptr; | ||||
|                 return bound == val; | ||||
|             } | ||||
| 
 | ||||
|             auto& vec = is_lower ? m_lower_terms : m_upper_terms; | ||||
|             lpvar ti = lp::tv::unmask_term(vi); | ||||
|             if (vec.size() > ti) { | ||||
|                 constraint_bound& b = vec[ti]; | ||||
|                 ci = b.first; | ||||
|                 return ci != UINT_MAX && bound == b.second; | ||||
|                 auto const& [ci, coeff] = vec[ti]; | ||||
|                 if (ci == UINT_MAX) | ||||
|                     return false; | ||||
|                 dep = lp().dep_manager().mk_leaf(ci); | ||||
|                 return bound == coeff; | ||||
|             } | ||||
|             else { | ||||
|                 return false; | ||||
|  | @ -3073,10 +3077,10 @@ public: | |||
|             bool is_strict = false; | ||||
|             rational b; | ||||
|             if (is_lower) { | ||||
|                 return lp().has_lower_bound(vi, ci, b, is_strict) && b == bound && !is_strict; | ||||
|                 return lp().has_lower_bound(vi, dep, b, is_strict) && b == bound && !is_strict; | ||||
|             } | ||||
|             else { | ||||
|                 return lp().has_upper_bound(vi, ci, b, is_strict) && b == bound && !is_strict; | ||||
|                 return lp().has_upper_bound(vi, dep, b, is_strict) && b == bound && !is_strict; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -3089,7 +3093,7 @@ public: | |||
| 
 | ||||
|     void report_equality_of_fixed_vars(unsigned vi1, unsigned vi2) { | ||||
|         rational bound(0); | ||||
|         lp::constraint_index ci1, ci2, ci3, ci4; | ||||
|         u_dependency* ci1 = nullptr, *ci2 = nullptr, *ci3 = nullptr, *ci4 = nullptr; | ||||
|         theory_var v1 = lp().local_to_external(vi1); | ||||
|         theory_var v2 = lp().local_to_external(vi2); | ||||
|         TRACE("arith", tout << "fixed: " << mk_pp(get_owner(v1), m) << " " << mk_pp(get_owner(v2), m) << "\n";); | ||||
|  | @ -3141,7 +3145,7 @@ public: | |||
|         ctx().assign_eq(x, y, eq_justification(js)); | ||||
|     } | ||||
|      | ||||
|     void fixed_var_eh(theory_var v, lp::tv t, lp::constraint_index ci1, lp::constraint_index ci2, rational const& bound) { | ||||
|     void fixed_var_eh(theory_var v, lp::tv t, u_dependency* dep, rational const& bound) { | ||||
|         theory_var w = null_theory_var; | ||||
|         enode* x = get_enode(v); | ||||
|         if (m_value2var.find(bound, w))  | ||||
|  | @ -3158,8 +3162,7 @@ public: | |||
|         if (x->get_root() == y->get_root()) | ||||
|             return; | ||||
|         reset_evidence(); | ||||
|         set_evidence(ci1, m_core, m_eqs); | ||||
|         set_evidence(ci2, m_core, m_eqs); | ||||
|         set_evidence(dep, m_core, m_eqs); | ||||
|         ++m_stats.m_fixed_eqs; | ||||
|         assign_eq(v, w);                     | ||||
|     } | ||||
|  | @ -3194,6 +3197,11 @@ public: | |||
| 
 | ||||
|     // lp::constraint_index const null_constraint_index = UINT_MAX; // not sure what a correct fix is
 | ||||
| 
 | ||||
|     void set_evidence(u_dependency* dep, literal_vector& core, svector<enode_pair>& eqs) { | ||||
|         for (auto ci : lp().flatten(dep)) | ||||
|             set_evidence(ci, core, eqs); | ||||
|     } | ||||
| 
 | ||||
|     void set_evidence(lp::constraint_index idx, literal_vector& core, svector<enode_pair>& eqs) { | ||||
|         if (idx == UINT_MAX) { | ||||
|             return; | ||||
|  | @ -3414,7 +3422,7 @@ public: | |||
|         if (!is_registered_var(v))  | ||||
|             return false;         | ||||
|         lpvar vi = get_lpvar(v); | ||||
|         lp::constraint_index ci; | ||||
|         u_dependency* ci; | ||||
|         return lp().has_lower_bound(vi, ci, val, is_strict); | ||||
|     } | ||||
| 
 | ||||
|  | @ -3433,8 +3441,8 @@ public: | |||
|         if (!is_registered_var(v)) | ||||
|             return false; | ||||
|         lpvar vi = get_lpvar(v); | ||||
|         lp::constraint_index ci; | ||||
|         return lp().has_upper_bound(vi, ci, val, is_strict); | ||||
|         u_dependency* dep = nullptr; | ||||
|         return lp().has_upper_bound(vi, dep, val, is_strict); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,13 +20,15 @@ namespace dd { | |||
|     } | ||||
|     void test1() { | ||||
|         pdd_manager m(4); | ||||
|         u_dependency_manager dm; | ||||
|         reslimit lim; | ||||
|         pdd v0 = m.mk_var(0); | ||||
|         pdd v1 = m.mk_var(1); | ||||
|         pdd v2 = m.mk_var(2); | ||||
|         pdd v3 = m.mk_var(3); | ||||
|          | ||||
|         solver gb(lim, m); | ||||
| 
 | ||||
|         solver gb(lim, dm, m); | ||||
|         gb.add(v1*v2 + v1*v3); | ||||
|         gb.add(v1 - 1); | ||||
|         gb.display(std::cout); | ||||
|  | @ -198,10 +200,11 @@ namespace dd { | |||
|     void test_simplify(expr_ref_vector& fmls, bool use_mod2) { | ||||
|         ast_manager& m = fmls.get_manager(); | ||||
|         unsigned_vector id2var; | ||||
|         u_dependency_manager dm; | ||||
| 
 | ||||
|         collect_id2var(id2var, fmls); | ||||
|         pdd_manager p(id2var.size(), use_mod2 ? pdd_manager::mod2_e : pdd_manager::zero_one_vars_e); | ||||
|         solver g(m.limit(), p); | ||||
|         solver g(m.limit(), dm, p); | ||||
| 
 | ||||
|         for (expr* e : subterms::ground(fmls)) { | ||||
|             add_def(id2var, to_app(e), m, p, g); | ||||
|  |  | |||
|  | @ -69,7 +69,7 @@ private: | |||
| 
 | ||||
|     value_manager &         m_vmanager; | ||||
|     allocator  &            m_allocator; | ||||
|     ptr_vector<dependency>  m_todo; | ||||
|     mutable ptr_vector<dependency>  m_todo; | ||||
| 
 | ||||
|     void inc_ref(value const & v) { | ||||
|         if (C::ref_count) | ||||
|  | @ -106,12 +106,9 @@ private: | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void unmark_todo() { | ||||
|         typename ptr_vector<dependency>::iterator it  = m_todo.begin(); | ||||
|         typename ptr_vector<dependency>::iterator end = m_todo.end(); | ||||
|         for (; it != end; ++it) { | ||||
|             (*it)->unmark(); | ||||
|         } | ||||
|     void unmark_todo() const { | ||||
|         for (auto* d : m_todo) | ||||
|             d->unmark(); | ||||
|         m_todo.reset(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -193,7 +190,7 @@ public: | |||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     void linearize(dependency * d, vector<value, false> & vs) { | ||||
|     void linearize(dependency * d, vector<value, false> & vs) const { | ||||
|         if (d) { | ||||
|             m_todo.reset(); | ||||
|             d->mark(); | ||||
|  | @ -300,7 +297,7 @@ public: | |||
|         return m_dep_manager.contains(d, v);  | ||||
|     } | ||||
| 
 | ||||
|     void linearize(dependency * d, vector<value, false> & vs) { | ||||
|     void linearize(dependency * d, vector<value, false> & vs) const { | ||||
|         return m_dep_manager.linearize(d, vs); | ||||
|     }     | ||||
|      | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue