mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-30 19:22:28 +00:00 
			
		
		
		
	add unsat core, activity, quick pass for viable
This commit is contained in:
		
							parent
							
								
									b82c3cfd33
								
							
						
					
					
						commit
						caef8d026f
					
				
					 6 changed files with 91 additions and 43 deletions
				
			
		|  | @ -56,6 +56,7 @@ namespace polysat { | |||
|         unsigned level(sat::bool_var var) const { SASSERT(is_assigned(var)); return m_level[var]; } | ||||
|         unsigned level(sat::literal lit) const { return level(lit.var()); } | ||||
|         clause* reason(sat::bool_var var) const { SASSERT(is_assigned(var)); return m_reason[var]; } | ||||
|         unsigned dep(sat::literal lit) const { return lit == sat::null_literal ? null_dependency : m_deps[lit.var()]; } | ||||
| 
 | ||||
|         clause* lemma(sat::bool_var var) const { SASSERT(is_decision(var)); return m_lemma[var]; } | ||||
|         | ||||
|  |  | |||
|  | @ -243,6 +243,7 @@ namespace polysat { | |||
|         for (unsigned v : m_vars) { | ||||
|             if (!is_pmarked(v)) | ||||
|                 continue; | ||||
|             s.inc_activity(v); | ||||
|             auto eq = s.eq(s.var(v), s.get_value(v)); | ||||
|             cm().ensure_bvar(eq.get()); | ||||
|             if (eq.bvalue(s) == l_undef)  | ||||
|  | @ -285,7 +286,11 @@ namespace polysat { | |||
|     bool conflict::resolve_value(pvar v) { | ||||
|         // NOTE:
 | ||||
|         // In the "standard" case where "v = val" is on the stack:
 | ||||
|         //      - core contains both false and true constraints (originally only false ones, but additional true ones may come from saturation)
 | ||||
|         //      - core contains both false and true constraints 
 | ||||
|         //        (originally only false ones, but additional true ones may come from saturation)
 | ||||
| 
 | ||||
|         // forbidden interval projection is performed at top level
 | ||||
|         SASSERT(v != conflict_var()); | ||||
| 
 | ||||
|         if (is_bailout()) { | ||||
|             if (!s.m_justification[v].is_decision()) | ||||
|  | @ -293,8 +298,7 @@ namespace polysat { | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         // forbidden interval projection is performed at top level
 | ||||
|         SASSERT(v != conflict_var()); | ||||
|         s.inc_activity(v);  | ||||
|          | ||||
|         m_vars.remove(v); | ||||
| 
 | ||||
|  |  | |||
|  | @ -147,7 +147,6 @@ namespace polysat { | |||
| #endif | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     bool solver::can_propagate() { | ||||
|         return m_qhead < m_search.size() && !is_conflict(); | ||||
|     } | ||||
|  | @ -175,6 +174,8 @@ namespace polysat { | |||
|         LOG_H2("Propagate bool " << lit << "@" << m_bvars.level(lit) << " " << m_level << " qhead: " << m_qhead); | ||||
|         signed_constraint c = lit2cnstr(lit); | ||||
|         SASSERT(c); | ||||
|         if (c->is_active()) | ||||
|             return; | ||||
|         activate_constraint(c); | ||||
|         auto& wlist = m_bvars.watch(~lit); | ||||
|         unsigned i = 0, j = 0, sz = wlist.size(); | ||||
|  | @ -460,8 +461,7 @@ namespace polysat { | |||
|      *    viable solutions by excluding the previous guess. | ||||
|      * | ||||
|      */ | ||||
|     void solver::resolve_conflict() { | ||||
|         IF_VERBOSE(1, verbose_stream() << "resolve conflict\n"); | ||||
|     void solver::resolve_conflict() {         | ||||
|         LOG_H2("Resolve conflict"); | ||||
|         LOG("\n" << *this); | ||||
|         LOG("search state: " << m_search); | ||||
|  | @ -521,6 +521,36 @@ namespace polysat { | |||
|         return m_conflict.resolve_value(v); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|     * Variable activity accounting. | ||||
|     * As a placeholder we increment activity  | ||||
|     * 1. when a variable assignment is used in a conflict. | ||||
|     * 2. when a variable propagation is resolved against. | ||||
|     * The hypothesis that this is useful should be tested against a  | ||||
|     * broader suite of benchmarks and tested with micro-benchmarks. | ||||
|     * It should be tested in conjunction with restarts. | ||||
|     */ | ||||
|     void solver::inc_activity(pvar v) { | ||||
|         unsigned& act = m_activity[v]; | ||||
|         act += m_activity_inc; | ||||
|         m_free_pvars.activity_increased_eh(v); | ||||
|         if (act > (1 << 24)) | ||||
|             rescale_activity(); | ||||
|     } | ||||
| 
 | ||||
|     void solver::decay_activity() { | ||||
|         m_activity_inc *= m_variable_decay; | ||||
|         m_activity_inc /= 100; | ||||
|     } | ||||
| 
 | ||||
|     void solver::rescale_activity() { | ||||
|         for (unsigned& act : m_activity) { | ||||
|             act >>= 14; | ||||
|         } | ||||
|         m_activity_inc >>= 14; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** Conflict resolution case where boolean literal 'lit' is on top of the stack 
 | ||||
|     *   NOTE: boolean resolution should work normally even in bailout mode. | ||||
|     */ | ||||
|  | @ -537,17 +567,12 @@ namespace polysat { | |||
|     } | ||||
| 
 | ||||
|     void solver::unsat_core(unsigned_vector& deps) { | ||||
|         NOT_IMPLEMENTED_YET();   // TODO: needs to be fixed to work with conflict_core
 | ||||
|         /*
 | ||||
|         deps.reset(); | ||||
|         p_dependency_ref conflict_dep(m_dm); | ||||
|         for (auto& c : m_conflict.units()) | ||||
|             if (c) | ||||
|                 conflict_dep = m_dm.mk_join(c->unit_dep(), conflict_dep); | ||||
|         for (auto& c : m_conflict.clauses()) | ||||
|             conflict_dep = m_dm.mk_join(c->dep(), conflict_dep); | ||||
|         m_dm.linearize(conflict_dep, deps); | ||||
|         */ | ||||
|         for (auto c : m_conflict) { | ||||
|             auto d = m_bvars.dep(c.blit()); | ||||
|             if (d != null_dependency) | ||||
|                 deps.push_back(d); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void solver::learn_lemma(clause& lemma) { | ||||
|  |  | |||
|  | @ -189,6 +189,13 @@ namespace polysat { | |||
|         void revert_decision(pvar v); | ||||
|         void revert_bool_decision(sat::literal lit); | ||||
| 
 | ||||
|         // activity of variables based on standard VSIDS
 | ||||
|         unsigned m_activity_inc = 128; | ||||
|         unsigned m_variable_decay = 110; | ||||
|         void inc_activity(pvar v); | ||||
|         void decay_activity(); | ||||
|         void rescale_activity(); | ||||
| 
 | ||||
|         void report_unsat(); | ||||
|         void learn_lemma(clause& lemma); | ||||
|         void backjump(unsigned new_level); | ||||
|  | @ -198,7 +205,7 @@ namespace polysat { | |||
|         void simplify(); | ||||
| 
 | ||||
|         unsigned m_conflicts_at_restart = 0; | ||||
|         unsigned m_restart_threshold = UINT_MAX; | ||||
|         unsigned m_restart_threshold = 100; | ||||
|         unsigned m_restart_init = 100; | ||||
|         unsigned m_luby_idx = 0; | ||||
|         bool should_restart(); | ||||
|  |  | |||
|  | @ -10,6 +10,14 @@ Author: | |||
|     Nikolaj Bjorner (nbjorner) 2021-03-19 | ||||
|     Jakob Rath 2021-04-6 | ||||
| 
 | ||||
| Notes: | ||||
| 
 | ||||
| TODO: Investigate in depth a notion of phase caching for variables. | ||||
| The Linear solver can be used to supply a phase in some cases. | ||||
| In other cases, the phase of a variable assignment across branches | ||||
| might be used in a call to is_viable. With phase caching on, it may | ||||
| just check if the cached phase is viable without detecting that it is a propagation. | ||||
| 
 | ||||
| --*/ | ||||
| 
 | ||||
| 
 | ||||
|  | @ -17,7 +25,6 @@ Author: | |||
| #include "math/polysat/viable.h" | ||||
| #include "math/polysat/solver.h" | ||||
| 
 | ||||
| 
 | ||||
| namespace polysat { | ||||
| 
 | ||||
|     viable::viable(solver& s) : s(s) {} | ||||
|  | @ -139,6 +146,13 @@ namespace polysat { | |||
|         if (!e) | ||||
|             return true; | ||||
|         entry* first = e; | ||||
|         entry* last = e->prev(); | ||||
| 
 | ||||
|         // quick check: last interval doesn't wrap around, so hi_val
 | ||||
|         // has not been covered
 | ||||
|         if (last->interval.lo_val() < last->interval.hi_val()) | ||||
|             return true; | ||||
| 
 | ||||
|         auto const& max_value = s.var2pdd(v).max_value(); | ||||
|         do { | ||||
|             if (e->interval.is_full()) | ||||
|  | @ -221,6 +235,17 @@ namespace polysat { | |||
| 
 | ||||
|         entry* first = e; | ||||
|         entry* last = first->prev(); | ||||
| 
 | ||||
|         // quick check: last interval does not wrap around
 | ||||
|         // and has space for 2 unassigned values.
 | ||||
|         auto& max_value = s.var2pdd(v).max_value(); | ||||
|         if (last->interval.lo_val() < last->interval.hi_val() && | ||||
|             last->interval.hi_val() < max_value) { | ||||
|             lo = last->interval.hi_val(); | ||||
|             return dd::find_t::multiple; | ||||
|         } | ||||
| 
 | ||||
|         // find lower bound
 | ||||
|         if (last->interval.currently_contains(lo)) | ||||
|             lo = last->interval.hi_val(); | ||||
|         do { | ||||
|  | @ -234,7 +259,8 @@ namespace polysat { | |||
|         if (e->interval.currently_contains(lo)) | ||||
|             return dd::find_t::empty; | ||||
| 
 | ||||
|         rational hi = s.var2pdd(v).max_value(); | ||||
|         // find upper bound
 | ||||
|         rational hi = max_value; | ||||
|         e = last; | ||||
|         do { | ||||
|             if (!e->interval.currently_contains(hi)) | ||||
|  | @ -271,7 +297,7 @@ namespace polysat { | |||
|             } | ||||
|             for (auto sc : e->side_cond) | ||||
|                 core.insert(sc); | ||||
|             e->src->set_var_dependent(); // ?
 | ||||
|             e->src->set_var_dependent();  | ||||
|             core.insert(e->src); | ||||
|             e = n; | ||||
|         }              | ||||
|  |  | |||
|  | @ -318,7 +318,7 @@ namespace polysat { | |||
|         s.add_eq(n*q1 - a + b); | ||||
|         s.add_eq(n*q2 + r2 - c*a + c*b); | ||||
|         s.add_ult(r2, n); | ||||
|         s.add_diseq(n); | ||||
|         s.add_diseq(r2); | ||||
|         s.check(); | ||||
|         s.expect_unsat(); | ||||
|     } | ||||
|  | @ -1067,19 +1067,7 @@ namespace polysat { | |||
| 
 | ||||
| void tst_polysat() { | ||||
| 
 | ||||
|  //   polysat::test_ineq_axiom1();
 | ||||
|  //   polysat::test_ineq_axiom2();
 | ||||
|  //   polysat::test_ineq_axiom3();
 | ||||
|  //   polysat::test_ineq_non_axiom1();
 | ||||
| #if 0 | ||||
|     polysat::test_ineq_non_axiom4(32, 5); | ||||
|     polysat::test_ineq_axiom4(); | ||||
|     polysat::test_ineq_axiom5(); | ||||
|     polysat::test_ineq_axiom6(); | ||||
| #endif | ||||
| 
 | ||||
|     // working
 | ||||
|     // NOT: polysat::test_fixed_point_arith_mul_div_inverse();
 | ||||
|              | ||||
|     // polysat::test_monot_bounds(8);
 | ||||
| 
 | ||||
|  | @ -1107,6 +1095,10 @@ void tst_polysat() { | |||
| 
 | ||||
|     polysat::test_var_minimize(); | ||||
| 
 | ||||
|     polysat::test_ineq1(); | ||||
|     polysat::test_ineq2(); | ||||
|     polysat::test_monot(); | ||||
| 
 | ||||
|     return; | ||||
| 
 | ||||
|     polysat::test_ineq_axiom1(); | ||||
|  | @ -1115,22 +1107,15 @@ void tst_polysat() { | |||
|     polysat::test_ineq_axiom4(); | ||||
|     polysat::test_ineq_axiom5(); | ||||
|     polysat::test_ineq_axiom6(); | ||||
| #if 0 | ||||
|     polysat::test_ineq_non_axiom4(32, 5); | ||||
| #endif | ||||
| 
 | ||||
|     // inefficient conflicts:
 | ||||
|     // Takes time: polysat::test_monot_bounds_full();
 | ||||
| 
 | ||||
| #if 0 | ||||
|     // worry about this later
 | ||||
|     polysat::test_ineq1(); | ||||
|     polysat::test_ineq2(); | ||||
| #endif | ||||
| 
 | ||||
|     // not working
 | ||||
|     polysat::test_monot_bounds_simple(8); | ||||
|     polysat::test_fixed_point_arith_div_mul_inverse(); | ||||
|     polysat::test_monot(); | ||||
|     polysat::test_ineq2(); | ||||
|     polysat::test_ineq1(); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue