mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Dev (#63)
* introduce int_solver.h Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * add int_solver class Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * track which var is an integer Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * add queries for integrality of vars Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * resurrect lp_tst in its own director lp Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * add file Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * add_constraint has got a body Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * fix add_constraint and substitute_terms_in_linear_expression Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * after merge with Z3Prover Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * adding stub check_int_feasibility() Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * Dev (#50) * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * small fix in lar_solver.cpp Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * adding some content to the new check_int_feasibility() Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * Dev (#51) * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding more nlsat Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * nlsat integration Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding constraints Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add missing initialization Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * test Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * Dev (#53) * change in a comment Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * Disabled debug output * removing FOCI2 interface from interp * remove foci reference from cmakelist.txt Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding more nlsat Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * nlsat integration Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding constraints Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add missing initialization Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding nra Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * debugging nra Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * updates to nra_solver integration to call it directly from theory_lra instead of over lar_solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * n/a Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * integrate nlsat Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * tidy Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * preserve is_int flag Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * remove a debug printout Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * Dev (#54) * change in a comment Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * Disabled debug output * removing FOCI2 interface from interp * remove foci reference from cmakelist.txt Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * initial skeletons for nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding more nlsat Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * nlsat integration Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding constraints Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add missing initialization Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding nra solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding nra Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * debugging nra Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * updates to nra_solver integration to call it directly from theory_lra instead of over lar_solver Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * n/a Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * integrate nlsat Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * tidy Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * use integer test from lra solver, updated it to work on term variables Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix equality check in assume-eq Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix model_is_int_feasible Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * untested gcd_test() Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * call fill_explanation_from_fixed_columns() Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * add the call to pivot_fixed_vars_from_basis() to int_solver.cpp::check() Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * port more of theory_arith_int.h Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * use statistics of lar_solver by theory_lra.cpp Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * port more code to int_solver.cpp Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * add an assert Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * more int porting Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * fix a bug in pivot_fixed_vars_from_basis Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * small change Signed-off-by: Lev Nachmanson <levnach@hotmail.com> * implement find_inf_int_base_column() Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * catch unregistered vars in add_var_bound Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * add a file Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * compile for vs2012 Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * fix asserts in add_var_bound Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * fix the lp_solver init when workig on an mps file Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * towards int_solver::check() Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * change in int_solver::check() signature Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * add handlers for lia moves Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * spacing Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * return branch from int_solver::check() Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * add a stub for mk_gomory_cut Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * Dev (#59) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * spacing Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * loops Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Dev (#60) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * spacing Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * loops Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * loops Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Dev (#61) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * spacing Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * loops Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * loops Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * more TRACE(arith_int) Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * fix the build Signed-off-by: Lev Nachmanson <levnach@microsoft.com> * loops Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Dev (#62) * add handlers for lia moves Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * spacing Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * loops Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * loops Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * loops Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * build fix Signed-off-by: Lev Nachmanson <levnach@microsoft.com>
This commit is contained in:
		
							parent
							
								
									c82aa5edce
								
							
						
					
					
						commit
						8bd029c657
					
				
					 4 changed files with 276 additions and 44 deletions
				
			
		| 
						 | 
				
			
			@ -55,13 +55,15 @@ namespace lra_lp {
 | 
			
		|||
    class bound {
 | 
			
		||||
        smt::bool_var    m_bv;
 | 
			
		||||
        smt::theory_var  m_var;
 | 
			
		||||
        bool             m_is_int;
 | 
			
		||||
        rational         m_value;
 | 
			
		||||
        bound_kind       m_bound_kind;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        bound(smt::bool_var bv, smt::theory_var v, rational const & val, bound_kind k):
 | 
			
		||||
        bound(smt::bool_var bv, smt::theory_var v, bool is_int, rational const & val, bound_kind k):
 | 
			
		||||
            m_bv(bv),
 | 
			
		||||
            m_var(v),
 | 
			
		||||
            m_is_int(is_int),
 | 
			
		||||
            m_value(val),
 | 
			
		||||
            m_bound_kind(k) {
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -69,12 +71,20 @@ namespace lra_lp {
 | 
			
		|||
        smt::theory_var get_var() const { return m_var; }
 | 
			
		||||
        smt::bool_var get_bv() const { return m_bv; }
 | 
			
		||||
        bound_kind get_bound_kind() const { return m_bound_kind; }
 | 
			
		||||
        bool is_int() const { return m_is_int; }
 | 
			
		||||
        rational const& get_value() const { return m_value; }
 | 
			
		||||
        inf_rational get_value(bool is_true) const {
 | 
			
		||||
            if (is_true) return inf_rational(m_value);                         // v >= value or v <= value
 | 
			
		||||
            if (m_bound_kind == lower_t) return inf_rational(m_value, false);  // v <= value - epsilon
 | 
			
		||||
            return inf_rational(m_value, true);                                // v >= value + epsilon
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            if (m_is_int) {
 | 
			
		||||
                if (m_bound_kind == lower_t) return inf_rational(m_value - rational::one()); // v <= value - 1
 | 
			
		||||
                return inf_rational(m_value + rational::one());                              // v >= value + 1
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                if (m_bound_kind == lower_t) return inf_rational(m_value, false);  // v <= value - epsilon
 | 
			
		||||
                return inf_rational(m_value, true);                                // v >= value + epsilon
 | 
			
		||||
            }
 | 
			
		||||
        } 
 | 
			
		||||
        virtual std::ostream& display(std::ostream& out) const {
 | 
			
		||||
            return out << "v" << get_var() << "  " << get_bound_kind() << " " << m_value;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -306,7 +316,6 @@ namespace smt {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        void found_not_handled(expr* n) {
 | 
			
		||||
            m_not_handled = n;
 | 
			
		||||
            if (is_app(n) && is_underspecified(to_app(n))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -762,7 +771,7 @@ namespace smt {
 | 
			
		|||
                found_not_handled(atom);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            lra_lp::bound* b = alloc(lra_lp::bound, bv, v, r, k);
 | 
			
		||||
            lp::bound* b = alloc(lp::bound, bv, v, is_int(v), r, k);
 | 
			
		||||
            m_bounds[v].push_back(b);
 | 
			
		||||
            updt_unassigned_bounds(v, +1);
 | 
			
		||||
            m_bounds_trail.push_back(v);
 | 
			
		||||
| 
						 | 
				
			
			@ -1217,33 +1226,49 @@ namespace smt {
 | 
			
		|||
            return FC_GIVEUP;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // create a bound atom representing term >= k
 | 
			
		||||
        lp::bound* mk_bound(lean::lar_term const& term, rational const& k) {
 | 
			
		||||
            NOT_IMPLEMENTED_YET();
 | 
			
		||||
            lp::bound_kind bkind = lp::bound_kind::lower_t;
 | 
			
		||||
            bool_var bv = null_bool_var; 
 | 
			
		||||
            theory_var v = null_theory_var;
 | 
			
		||||
            lp::bound* result = alloc(lp::bound, bv, v, k, bkind);
 | 
			
		||||
            return result;
 | 
			
		||||
        // create a bound atom representing term <= k
 | 
			
		||||
        app_ref mk_bound(lean::lar_term const& term, rational const& k) {
 | 
			
		||||
            SASSERT(k.is_int());
 | 
			
		||||
            app_ref t = mk_term(term, true);
 | 
			
		||||
            app_ref atom(a.mk_le(t, a.mk_numeral(k, true)), m);
 | 
			
		||||
            TRACE("arith", tout << atom << "\n";
 | 
			
		||||
                  m_solver->print_term(term, tout << "bound atom: "); tout << " <= " << k << "\n";
 | 
			
		||||
                  display(tout);
 | 
			
		||||
                  );
 | 
			
		||||
            ctx().internalize(atom, true);
 | 
			
		||||
            ctx().mark_as_relevant(atom.get());
 | 
			
		||||
            return atom;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        lbool check_lia() {
 | 
			
		||||
            std::cout << "called check_lia()\n";
 | 
			
		||||
            if (m.canceled()) return l_undef;
 | 
			
		||||
            lean::lar_term term;
 | 
			
		||||
            lean::mpq k;
 | 
			
		||||
            lean::explanation ex; // TBD, this should be streamlined accross different explanations
 | 
			
		||||
            switch(m_lia->check(term, k, ex)) {
 | 
			
		||||
            case lean::lia_move::ok:
 | 
			
		||||
                return l_true;
 | 
			
		||||
            case lean::lia_move::branch:
 | 
			
		||||
            case lean::lia_move::branch: {
 | 
			
		||||
                (void)mk_bound(term, k);
 | 
			
		||||
                // branch on term <= k
 | 
			
		||||
                NOT_IMPLEMENTED_YET();
 | 
			
		||||
                // at this point we have a new unassigned atom that the 
 | 
			
		||||
                // SAT core assigns a value to
 | 
			
		||||
                return l_false;
 | 
			
		||||
            case lean::lia_move::cut:
 | 
			
		||||
            }
 | 
			
		||||
            case lean::lia_move::cut: {
 | 
			
		||||
                // m_explanation implies term <= k
 | 
			
		||||
                m_explanation = ex.m_explanation;
 | 
			
		||||
                NOT_IMPLEMENTED_YET();
 | 
			
		||||
                app_ref b = mk_bound(term, k);
 | 
			
		||||
                m_eqs.reset();
 | 
			
		||||
                m_core.reset();
 | 
			
		||||
                m_params.reset();
 | 
			
		||||
                for (auto const& ev : ex.m_explanation) {
 | 
			
		||||
                    if (!ev.first.is_zero()) { 
 | 
			
		||||
                        set_evidence(ev.second);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                assign(literal(ctx().get_bool_var(b), false));
 | 
			
		||||
                return l_false;
 | 
			
		||||
            }
 | 
			
		||||
            case lean::lia_move::conflict:
 | 
			
		||||
                // ex contains unsat core
 | 
			
		||||
                m_explanation = ex.m_explanation;
 | 
			
		||||
| 
						 | 
				
			
			@ -2052,7 +2077,15 @@ namespace smt {
 | 
			
		|||
                ++m_stats.m_assert_upper;
 | 
			
		||||
            }
 | 
			
		||||
            auto vi = get_var_index(b.get_var());
 | 
			
		||||
            auto ci = m_solver->add_var_bound(vi, k, b.get_value());
 | 
			
		||||
            rational bound = b.get_value();
 | 
			
		||||
            lean::constraint_index ci;
 | 
			
		||||
            if (is_int && !is_true) {
 | 
			
		||||
                rational bound = b.get_value(false).get_rational();
 | 
			
		||||
                ci = m_solver->add_var_bound(vi, k, bound);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                ci = m_solver->add_var_bound(vi, k, b.get_value());
 | 
			
		||||
            }
 | 
			
		||||
            TRACE("arith", tout << "v" << b.get_var() << "\n";);
 | 
			
		||||
            add_ineq_constraint(ci, literal(bv, !is_true));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2522,8 +2555,21 @@ namespace smt {
 | 
			
		|||
                    expr* o = get_enode(w)->get_owner();
 | 
			
		||||
                    args.push_back(a.mk_mul(a.mk_numeral(ti.second, is_int), o));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (!term.m_v.is_zero()) {
 | 
			
		||||
                args.push_back(a.mk_numeral(term.m_v, is_int));
 | 
			
		||||
                return app_ref(a.mk_add(args.size(), args.c_ptr()), m);
 | 
			
		||||
            }
 | 
			
		||||
            if (args.size() == 1) {
 | 
			
		||||
                return app_ref(to_app(args[0].get()), m);
 | 
			
		||||
            }
 | 
			
		||||
            return app_ref(a.mk_add(args.size(), args.c_ptr()), m);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        app_ref mk_obj(theory_var v) {
 | 
			
		||||
            lean::var_index vi = m_theory_var2var_index[v];
 | 
			
		||||
            bool is_int = a.is_int(get_enode(v)->get_owner());
 | 
			
		||||
            if (m_solver->is_term(vi)) {           
 | 
			
		||||
                return mk_term(m_solver->get_term(vi), is_int);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                theory_var w = m_var_index2theory_var[vi];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -101,6 +101,186 @@ int int_solver::find_inf_int_boxed_base_column_with_smallest_range() {
 | 
			
		|||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool int_solver::mk_gomory_cut(unsigned row_index, explanation & ex) {
 | 
			
		||||
    lean_assert(false);
 | 
			
		||||
    return true;
 | 
			
		||||
    /*
 | 
			
		||||
    const auto & row = m_lar_solver->A_r().m_rows[row_index];
 | 
			
		||||
            // The following assertion is wrong. It may be violated in mixed-integer problems.
 | 
			
		||||
    // SASSERT(!all_coeff_int(r));
 | 
			
		||||
    theory_var x_i = r.get_base_var();
 | 
			
		||||
        
 | 
			
		||||
    SASSERT(is_int(x_i));
 | 
			
		||||
    // The following assertion is wrong. It may be violated in mixed-real-interger problems.
 | 
			
		||||
    // The check is_gomory_cut_target will discard rows where any variable contains infinitesimals.
 | 
			
		||||
    // SASSERT(m_value[x_i].is_rational()); // infinitesimals are not used for integer variables
 | 
			
		||||
    SASSERT(!m_value[x_i].is_int());     // the base variable is not assigned to an integer value.
 | 
			
		||||
 | 
			
		||||
    if (constrain_free_vars(r) || !is_gomory_cut_target(r)) {
 | 
			
		||||
        TRACE("gomory_cut", tout << "failed to apply gomory cut:\n";
 | 
			
		||||
              tout << "constrain_free_vars(r):  " << constrain_free_vars(r) << "\n";);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    TRACE("gomory_cut", tout << "applying cut at:\n"; display_row_info(tout, r););
 | 
			
		||||
        
 | 
			
		||||
    antecedents ante(*this);
 | 
			
		||||
 | 
			
		||||
    m_stats.m_gomory_cuts++;
 | 
			
		||||
 | 
			
		||||
    // gomory will be   pol >= k
 | 
			
		||||
    numeral k(1);
 | 
			
		||||
    buffer<row_entry> pol;
 | 
			
		||||
        
 | 
			
		||||
    numeral f_0  = Ext::fractional_part(m_value[x_i]);
 | 
			
		||||
    numeral one_minus_f_0 = numeral(1) - f_0; 
 | 
			
		||||
    SASSERT(!f_0.is_zero());
 | 
			
		||||
    SASSERT(!one_minus_f_0.is_zero());
 | 
			
		||||
        
 | 
			
		||||
    numeral lcm_den(1);
 | 
			
		||||
    unsigned num_ints = 0;
 | 
			
		||||
 | 
			
		||||
    typename vector<row_entry>::const_iterator it  = r.begin_entries();
 | 
			
		||||
    typename vector<row_entry>::const_iterator end = r.end_entries();
 | 
			
		||||
    for (; it != end; ++it) {
 | 
			
		||||
        if (!it->is_dead() && it->m_var != x_i) {
 | 
			
		||||
            theory_var x_j   = it->m_var;
 | 
			
		||||
            numeral a_ij = it->m_coeff;
 | 
			
		||||
            a_ij.neg();  // make the used format compatible with the format used in: Integrating Simplex with DPLL(T)
 | 
			
		||||
            if (is_real(x_j)) {
 | 
			
		||||
                numeral new_a_ij;
 | 
			
		||||
                if (at_lower(x_j)) {
 | 
			
		||||
                    if (a_ij.is_pos()) {
 | 
			
		||||
                        new_a_ij  =  a_ij / one_minus_f_0;
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        new_a_ij  =  a_ij / f_0;
 | 
			
		||||
                        new_a_ij.neg();
 | 
			
		||||
                    }
 | 
			
		||||
                    k.addmul(new_a_ij, lower_bound(x_j).get_rational());
 | 
			
		||||
                    lower(x_j)->push_justification(ante, new_a_ij, coeffs_enabled());
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    SASSERT(at_upper(x_j));
 | 
			
		||||
                    if (a_ij.is_pos()) {
 | 
			
		||||
                        new_a_ij =   a_ij / f_0; 
 | 
			
		||||
                        new_a_ij.neg(); // the upper terms are inverted.
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        new_a_ij =   a_ij / one_minus_f_0; 
 | 
			
		||||
                    }
 | 
			
		||||
                    k.addmul(new_a_ij, upper_bound(x_j).get_rational());
 | 
			
		||||
                    upper(x_j)->push_justification(ante, new_a_ij, coeffs_enabled());
 | 
			
		||||
                }
 | 
			
		||||
                TRACE("gomory_cut_detail", tout << a_ij << "*v" << x_j << " k: " << k << "\n";);
 | 
			
		||||
                pol.push_back(row_entry(new_a_ij, x_j));
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                ++num_ints;
 | 
			
		||||
                SASSERT(is_int(x_j));
 | 
			
		||||
                numeral f_j = Ext::fractional_part(a_ij);
 | 
			
		||||
                TRACE("gomory_cut_detail", 
 | 
			
		||||
                      tout << a_ij << "*v" << x_j << "\n";
 | 
			
		||||
                      tout << "fractional_part: " << Ext::fractional_part(a_ij) << "\n";
 | 
			
		||||
                      tout << "f_j: " << f_j << "\n";
 | 
			
		||||
                      tout << "f_0: " << f_0 << "\n";
 | 
			
		||||
                      tout << "one_minus_f_0: " << one_minus_f_0 << "\n";);
 | 
			
		||||
                if (!f_j.is_zero()) {
 | 
			
		||||
                    numeral new_a_ij;
 | 
			
		||||
                    if (at_lower(x_j)) {
 | 
			
		||||
                        if (f_j <= one_minus_f_0) {
 | 
			
		||||
                            new_a_ij = f_j / one_minus_f_0;
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                            new_a_ij = (numeral(1) - f_j) / f_0;
 | 
			
		||||
                        }
 | 
			
		||||
                        k.addmul(new_a_ij, lower_bound(x_j).get_rational());
 | 
			
		||||
                        lower(x_j)->push_justification(ante, new_a_ij, coeffs_enabled());
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        SASSERT(at_upper(x_j));
 | 
			
		||||
                        if (f_j <= f_0) {
 | 
			
		||||
                            new_a_ij = f_j / f_0;
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                            new_a_ij = (numeral(1) - f_j) / one_minus_f_0;
 | 
			
		||||
                        }
 | 
			
		||||
                        new_a_ij.neg(); // the upper terms are inverted
 | 
			
		||||
                        k.addmul(new_a_ij, upper_bound(x_j).get_rational());
 | 
			
		||||
                        upper(x_j)->push_justification(ante, new_a_ij, coeffs_enabled());
 | 
			
		||||
                    }
 | 
			
		||||
                    TRACE("gomory_cut_detail", tout << "new_a_ij: " << new_a_ij << " k: " << k << "\n";);
 | 
			
		||||
                    pol.push_back(row_entry(new_a_ij, x_j));
 | 
			
		||||
                    lcm_den = lcm(lcm_den, denominator(new_a_ij));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    CTRACE("empty_pol", pol.empty(), display_row_info(tout, r););
 | 
			
		||||
 | 
			
		||||
    expr_ref bound(get_manager());
 | 
			
		||||
    if (pol.empty()) {
 | 
			
		||||
        SASSERT(k.is_pos());
 | 
			
		||||
        // conflict 0 >= k where k is positive
 | 
			
		||||
        set_conflict(ante, ante, "gomory-cut");
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    else if (pol.size() == 1) {
 | 
			
		||||
        theory_var v = pol[0].m_var;
 | 
			
		||||
        k /= pol[0].m_coeff;
 | 
			
		||||
        bool is_lower = pol[0].m_coeff.is_pos();
 | 
			
		||||
        if (is_int(v) && !k.is_int()) {
 | 
			
		||||
            k = is_lower?ceil(k):floor(k);
 | 
			
		||||
        }
 | 
			
		||||
        rational _k = k.to_rational();
 | 
			
		||||
        if (is_lower)
 | 
			
		||||
            bound = m_util.mk_ge(get_enode(v)->get_owner(), m_util.mk_numeral(_k, is_int(v)));
 | 
			
		||||
        else
 | 
			
		||||
            bound = m_util.mk_le(get_enode(v)->get_owner(), m_util.mk_numeral(_k, is_int(v)));
 | 
			
		||||
    }
 | 
			
		||||
    else { 
 | 
			
		||||
        if (num_ints > 0) {
 | 
			
		||||
            lcm_den = lcm(lcm_den, denominator(k));
 | 
			
		||||
            TRACE("gomory_cut_detail", tout << "k: " << k << " lcm_den: " << lcm_den << "\n";
 | 
			
		||||
                  for (unsigned i = 0; i < pol.size(); i++) {
 | 
			
		||||
                      tout << pol[i].m_coeff << " " << pol[i].m_var << "\n";
 | 
			
		||||
                  }
 | 
			
		||||
                  tout << "k: " << k << "\n";);
 | 
			
		||||
            SASSERT(lcm_den.is_pos());
 | 
			
		||||
            if (!lcm_den.is_one()) {
 | 
			
		||||
                // normalize coefficients of integer parameters to be integers.
 | 
			
		||||
                unsigned n = pol.size();
 | 
			
		||||
                for (unsigned i = 0; i < n; i++) {
 | 
			
		||||
                    pol[i].m_coeff *= lcm_den;
 | 
			
		||||
                    SASSERT(!is_int(pol[i].m_var) || pol[i].m_coeff.is_int());
 | 
			
		||||
                }
 | 
			
		||||
                k *= lcm_den;
 | 
			
		||||
            }
 | 
			
		||||
            TRACE("gomory_cut_detail", tout << "after *lcm\n";
 | 
			
		||||
                  for (unsigned i = 0; i < pol.size(); i++) {
 | 
			
		||||
                      tout << pol[i].m_coeff << " * v" << pol[i].m_var << "\n";
 | 
			
		||||
                  }
 | 
			
		||||
                  tout << "k: " << k << "\n";);
 | 
			
		||||
        }
 | 
			
		||||
        mk_polynomial_ge(pol.size(), pol.c_ptr(), k.to_rational(), bound);            
 | 
			
		||||
    }
 | 
			
		||||
    TRACE("gomory_cut", tout << "new cut:\n" << bound << "\n"; ante.display(tout););
 | 
			
		||||
    literal l     = null_literal;
 | 
			
		||||
    context & ctx = get_context();
 | 
			
		||||
    ctx.internalize(bound, true);
 | 
			
		||||
    l = ctx.get_literal(bound);
 | 
			
		||||
    ctx.mark_as_relevant(l);
 | 
			
		||||
    dump_lemmas(l, ante);
 | 
			
		||||
    ctx.assign(l, ctx.mk_justification(
 | 
			
		||||
                                       gomory_cut_justification(
 | 
			
		||||
                                                                get_id(), ctx.get_region(), 
 | 
			
		||||
                                                                ante.lits().size(), ante.lits().c_ptr(), 
 | 
			
		||||
                                                                ante.eqs().size(), ante.eqs().c_ptr(), ante, l)));
 | 
			
		||||
    return true;
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) {
 | 
			
		||||
    lean_assert(is_feasible());
 | 
			
		||||
    init_inf_int_set();
 | 
			
		||||
| 
						 | 
				
			
			@ -129,32 +309,35 @@ lia_move int_solver::check(lar_term& t, mpq& k, explanation& ex) {
 | 
			
		|||
 | 
			
		||||
    if ((++m_branch_cut_counter) % settings().m_int_branch_cut_threshold == 0) {
 | 
			
		||||
        move_non_base_vars_to_bounds();
 | 
			
		||||
        /*
 | 
			
		||||
        if (!make_feasible()) {
 | 
			
		||||
            TRACE("arith_int", tout << "failed to move variables to bounds.\n";);
 | 
			
		||||
            failed();
 | 
			
		||||
            return FC_CONTINUE;
 | 
			
		||||
        lp_status st = m_lar_solver->find_feasible_solution();
 | 
			
		||||
        if (st != lp_status::FEASIBLE && st != lp_status::OPTIMAL) {
 | 
			
		||||
            return lia_move::give_up;
 | 
			
		||||
        }
 | 
			
		||||
        int int_var = find_inf_int_base_var();
 | 
			
		||||
        if (int_var != null_int) {
 | 
			
		||||
            TRACE("arith_int", tout << "v" << int_var << " does not have an integer assignment: " << get_value(int_var) << "\n";);
 | 
			
		||||
            SASSERT(is_base(int_var));
 | 
			
		||||
            row const & r = m_rows[get_var_row(int_var)];
 | 
			
		||||
            if (!mk_gomory_cut(r)) {
 | 
			
		||||
        int j = find_inf_int_base_column();
 | 
			
		||||
        if (j != -1) {
 | 
			
		||||
            TRACE("arith_int", tout << "j = " << j << " does not have an integer assignment: " << get_value(j) << "\n";);
 | 
			
		||||
            unsigned row_index = m_lar_solver->m_mpq_lar_core_solver.m_r_heading[j];
 | 
			
		||||
            if (!mk_gomory_cut(row_index, ex)) {
 | 
			
		||||
                return lia_move::give_up;
 | 
			
		||||
                // silent failure
 | 
			
		||||
            }
 | 
			
		||||
            return FC_CONTINUE;
 | 
			
		||||
            }*/
 | 
			
		||||
            return lia_move::cut;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        int j = find_inf_int_base_column();
 | 
			
		||||
        /*
 | 
			
		||||
        if (j != -1) {
 | 
			
		||||
            TRACE("arith_int", tout << "v" << j << " does not have an integer assignment: " << get_value(j) << "\n";);
 | 
			
		||||
            // apply branching 
 | 
			
		||||
            branch_infeasible_int_var(int_var);
 | 
			
		||||
            return false;
 | 
			
		||||
            }*/
 | 
			
		||||
            TRACE("arith_int", tout << "j" << j << " does not have an integer assignment: " << get_value(j) << "\n";);
 | 
			
		||||
 | 
			
		||||
            lean_assert(t.is_empty());
 | 
			
		||||
            t.add_to_map(j, mpq(1));
 | 
			
		||||
            k = floor(get_value(j));
 | 
			
		||||
            TRACE("arith_int", tout << "branching v" << j << " = " << get_value(j) << "\n";
 | 
			
		||||
              display_column(tout, j);
 | 
			
		||||
              tout << "k = " << k << std::endl;
 | 
			
		||||
              );
 | 
			
		||||
            return lia_move::branch;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    //    return true;
 | 
			
		||||
    return lia_move::give_up;
 | 
			
		||||
| 
						 | 
				
			
			@ -259,7 +442,6 @@ mpq get_denominators_lcm(iterator_on_row<mpq> &it) {
 | 
			
		|||
    
 | 
			
		||||
bool int_solver::gcd_test_for_row(static_matrix<mpq, numeric_pair<mpq>> & A, unsigned i, explanation & ex) {
 | 
			
		||||
    iterator_on_row<mpq> it(A.m_rows[i]);
 | 
			
		||||
    std::cout << "gcd_test_for_row(" << i << ")\n";
 | 
			
		||||
    mpq lcm_den = get_denominators_lcm(it);
 | 
			
		||||
    mpq consts(0);
 | 
			
		||||
    mpq gcds(0);
 | 
			
		||||
| 
						 | 
				
			
			@ -350,8 +532,6 @@ bool int_solver::ext_gcd_test(iterator_on_row<mpq> & it,
 | 
			
		|||
                              mpq const & least_coeff, 
 | 
			
		||||
                              mpq const & lcm_den,
 | 
			
		||||
                              mpq const & consts, explanation& ex) {
 | 
			
		||||
 | 
			
		||||
    std::cout << "calling ext_gcd_test" << std::endl;
 | 
			
		||||
    mpq gcds(0);
 | 
			
		||||
    mpq l(consts);
 | 
			
		||||
    mpq u(consts);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -96,5 +96,7 @@ private:
 | 
			
		|||
    int find_inf_int_boxed_base_column_with_smallest_range();
 | 
			
		||||
    lp_settings& settings();
 | 
			
		||||
    void move_non_base_vars_to_bounds();
 | 
			
		||||
    void branch_infeasible_int_var(unsigned);
 | 
			
		||||
    bool mk_gomory_cut(unsigned row_index, explanation & ex);
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,6 +36,10 @@ struct lar_term {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_empty() const {
 | 
			
		||||
        return m_coeffs.size() == 0 && is_zero(m_v);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    unsigned size() const { return static_cast<unsigned>(m_coeffs.size()); }
 | 
			
		||||
    
 | 
			
		||||
    const std::unordered_map<unsigned, mpq> & coeffs() const {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue