mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 11:42:28 +00:00 
			
		
		
		
	na
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
		
							parent
							
								
									83dcc7841a
								
							
						
					
					
						commit
						2df104d9f0
					
				
					 3 changed files with 130 additions and 66 deletions
				
			
		|  | @ -45,6 +45,18 @@ namespace polysat { | ||||||
|         return !b.is_false(); |         return !b.is_false(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     void solver::add_non_viable(unsigned var, rational const& val) { | ||||||
|  |         bdd value = m_bdd.mk_true(); | ||||||
|  |         for (unsigned k = size(var); k-- > 0; )  | ||||||
|  |             value &= val.get_bit(k) ? m_bdd.mk_var(k) : m_bdd.mk_nvar(k); | ||||||
|  |         m_viable[var] &= !value;         | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     lbool solver::find_viable(unsigned var, rational & val) { | ||||||
|  |         return l_false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     struct solver::t_del_var : public trail { |     struct solver::t_del_var : public trail { | ||||||
|         solver& s; |         solver& s; | ||||||
|         t_del_var(solver& s): s(s) {} |         t_del_var(solver& s): s(s) {} | ||||||
|  | @ -55,6 +67,8 @@ namespace polysat { | ||||||
|     solver::solver(trail_stack& s):  |     solver::solver(trail_stack& s):  | ||||||
|         m_trail(s), |         m_trail(s), | ||||||
|         m_bdd(1000), |         m_bdd(1000), | ||||||
|  |         m_dep_manager(m_value_manager, m_alloc), | ||||||
|  |         m_lemma_dep(nullptr, m_dep_manager), | ||||||
|         m_free_vars(m_activity) { |         m_free_vars(m_activity) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -102,7 +116,8 @@ namespace polysat { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void solver::add_eq(pdd const& p, unsigned dep) { |     void solver::add_eq(pdd const& p, unsigned dep) { | ||||||
|         constraint* c = constraint::eq(m_level, p, m_dep_manager.mk_leaf(dep)); |         p_dependency_ref d(m_dep_manager.mk_leaf(dep), m_dep_manager); | ||||||
|  |         constraint* c = constraint::eq(m_level, p, d); | ||||||
|         m_constraints.push_back(c); |         m_constraints.push_back(c); | ||||||
|         add_watch(*c); |         add_watch(*c); | ||||||
|     } |     } | ||||||
|  | @ -135,7 +150,7 @@ namespace polysat { | ||||||
| 
 | 
 | ||||||
|     void solver::assign(unsigned var, unsigned index, bool value, unsigned dep) { |     void solver::assign(unsigned var, unsigned index, bool value, unsigned dep) { | ||||||
|         m_viable[var] &= value ? m_bdd.mk_var(index) : m_bdd.mk_nvar(index); |         m_viable[var] &= value ? m_bdd.mk_var(index) : m_bdd.mk_nvar(index); | ||||||
|         m_trail.push(vector_value_trail<u_dependency*, false>(m_vdeps, var)); |         m_trail.push(vector_value_trail<p_dependency*, false>(m_vdeps, var)); | ||||||
|         m_vdeps[var] = m_dep_manager.mk_join(m_vdeps[var], m_dep_manager.mk_leaf(dep)); |         m_vdeps[var] = m_dep_manager.mk_join(m_vdeps[var], m_dep_manager.mk_leaf(dep)); | ||||||
|         if (m_viable[var].is_false()) { |         if (m_viable[var].is_false()) { | ||||||
|             // TBD: set conflict
 |             // TBD: set conflict
 | ||||||
|  | @ -357,8 +372,7 @@ namespace polysat { | ||||||
|         m_conflict = nullptr; |         m_conflict = nullptr; | ||||||
|         pdd p = c.p(); |         pdd p = c.p(); | ||||||
|         m_lemma_level = c.level();         |         m_lemma_level = c.level();         | ||||||
|         m_lemma_deps.reset(); |         m_lemma_dep = c.dep(); | ||||||
|         m_lemma_deps.push_back(c.dep()); |  | ||||||
|         unsigned new_lemma_level = 0; |         unsigned new_lemma_level = 0; | ||||||
|         reset_marks(); |         reset_marks(); | ||||||
|         for (auto v : c.vars()) |         for (auto v : c.vars()) | ||||||
|  | @ -442,27 +456,32 @@ namespace polysat { | ||||||
|         auto v = m_search[i]; |         auto v = m_search[i]; | ||||||
|         SASSERT(m_justification[v].is_decision()); |         SASSERT(m_justification[v].is_decision()); | ||||||
|         SASSERT(m_lemma_level <= m_justification[v].level()); |         SASSERT(m_lemma_level <= m_justification[v].level()); | ||||||
|         // 
 |         constraint* c = constraint::eq(m_lemma_level, p, m_lemma_dep); | ||||||
|         // TBD: convert m_lemma_deps into deps.
 |  | ||||||
|         // the scope of the new constraint should be confined to 
 |  | ||||||
|         // m_lemma_level so could be below the current user scope.
 |  | ||||||
|         // What to do in this case is TBD.
 |  | ||||||
|         // 
 |  | ||||||
|         unsigned level = m_lemma_level; |  | ||||||
|         u_dependency* deps = nullptr;  |  | ||||||
|         constraint* c = constraint::eq(level, p, deps); |  | ||||||
|         m_cjust[v].push_back(c);         |         m_cjust[v].push_back(c);         | ||||||
|         add_lemma(c); |         add_lemma(c); | ||||||
|  |         add_non_viable(v, m_value[v]); | ||||||
|  | 
 | ||||||
|  |         // TBD conditions for when backjumping applies to be clarified.
 | ||||||
|  |         unsigned new_level = m_justification[v].level(); | ||||||
|  |         backjump(new_level); | ||||||
|         // 
 |         // 
 | ||||||
|         // TBD: remove current value from viable
 |         // find a new decision if there is one, 
 | ||||||
|         // m_values[v]
 |  | ||||||
|         // 
 |  | ||||||
|         // 1. undo levels until i
 |  | ||||||
|         // 2. find a new decision if there is one, 
 |  | ||||||
|         // propagate if decision is singular,
 |         // propagate if decision is singular,
 | ||||||
|         // otherwise if there are no viable decisions, backjump
 |         // otherwise if there are no viable decisions, backjump
 | ||||||
|         //  and set a new conflict.
 |         //  and set a new conflict.
 | ||||||
|         // 
 |         // 
 | ||||||
|  |         rational value; | ||||||
|  |         switch (find_viable(v, value)) { | ||||||
|  |         case l_true: | ||||||
|  |             // unit propagation
 | ||||||
|  |             break; | ||||||
|  |         case l_undef: | ||||||
|  |             // branch
 | ||||||
|  |             break; | ||||||
|  |         case l_false: | ||||||
|  |             // no viable.
 | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     void solver::backjump(unsigned new_level) { |     void solver::backjump(unsigned new_level) { | ||||||
|  | @ -490,10 +509,6 @@ namespace polysat { | ||||||
|      |      | ||||||
|     /**
 |     /**
 | ||||||
|      * Return residue of superposing p and q with respect to v. |      * Return residue of superposing p and q with respect to v. | ||||||
|      *  |  | ||||||
|      * TBD: should also collect dependencies (deps) |  | ||||||
|      * and maximal level of constraints so learned lemma |  | ||||||
|      * is given the appropriate level. |  | ||||||
|      */ |      */ | ||||||
|     pdd solver::resolve(unsigned v, pdd const& p, unsigned& resolve_level) { |     pdd solver::resolve(unsigned v, pdd const& p, unsigned& resolve_level) { | ||||||
|         resolve_level = 0; |         resolve_level = 0; | ||||||
|  | @ -507,7 +522,7 @@ namespace polysat { | ||||||
|                     // add parity condition to presere falsification
 |                     // add parity condition to presere falsification
 | ||||||
|                     degree = r.degree(v); |                     degree = r.degree(v); | ||||||
|                     resolve_level = std::max(resolve_level, c->level()); |                     resolve_level = std::max(resolve_level, c->level()); | ||||||
|                     m_lemma_deps.push_back(c->dep()); |                     m_lemma_dep = m_dep_manager.mk_join(m_lemma_dep.get(), c->dep()); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -538,14 +553,12 @@ namespace polysat { | ||||||
| 
 | 
 | ||||||
|     void solver::push() { |     void solver::push() { | ||||||
|         push_level(); |         push_level(); | ||||||
|         m_dep_manager.push_scope(); |  | ||||||
|         m_scopes.push_back(m_level); |         m_scopes.push_back(m_level); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void solver::pop(unsigned num_scopes) { |     void solver::pop(unsigned num_scopes) { | ||||||
|         unsigned base_level = m_scopes[m_scopes.size() - num_scopes]; |         unsigned base_level = m_scopes[m_scopes.size() - num_scopes]; | ||||||
|         pop_levels(m_level - base_level - 1); |         pop_levels(m_level - base_level - 1); | ||||||
|         m_dep_manager.pop_scope(num_scopes); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool solver::at_base_level() const { |     bool solver::at_base_level() const { | ||||||
|  |  | ||||||
|  | @ -30,6 +30,23 @@ namespace polysat { | ||||||
|     typedef dd::pdd pdd; |     typedef dd::pdd pdd; | ||||||
|     typedef dd::bdd bdd; |     typedef dd::bdd bdd; | ||||||
| 
 | 
 | ||||||
|  |     struct dep_value_manager { | ||||||
|  |         void inc_ref(unsigned) {} | ||||||
|  |         void dec_ref(unsigned) {} | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     struct dep_config { | ||||||
|  |         typedef dep_value_manager value_manager; | ||||||
|  |         typedef unsigned value; | ||||||
|  |         typedef small_object_allocator allocator; | ||||||
|  |         static const bool ref_count = false; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     typedef dependency_manager<dep_config> poly_dep_manager; | ||||||
|  |     typedef poly_dep_manager::dependency p_dependency; | ||||||
|  | 
 | ||||||
|  |     typedef obj_ref<p_dependency, poly_dep_manager> p_dependency_ref;  | ||||||
|  | 
 | ||||||
|     enum ckind_t { eq_t, ule_t, sle_t }; |     enum ckind_t { eq_t, ule_t, sle_t }; | ||||||
| 
 | 
 | ||||||
|     class constraint { |     class constraint { | ||||||
|  | @ -37,9 +54,9 @@ namespace polysat { | ||||||
|         ckind_t m_kind; |         ckind_t m_kind; | ||||||
|         pdd    m_poly; |         pdd    m_poly; | ||||||
|         pdd    m_other; |         pdd    m_other; | ||||||
|         u_dependency* m_dep; |         p_dependency_ref m_dep; | ||||||
|         unsigned_vector m_vars; |         unsigned_vector m_vars; | ||||||
|         constraint(unsigned lvl, pdd const& p, pdd const& q, u_dependency* dep, ckind_t k):  |         constraint(unsigned lvl, pdd const& p, pdd const& q, p_dependency_ref& dep, ckind_t k):  | ||||||
|             m_level(lvl), m_kind(k), m_poly(p), m_other(q), m_dep(dep) { |             m_level(lvl), m_kind(k), m_poly(p), m_other(q), m_dep(dep) { | ||||||
|             m_vars.append(p.free_vars()); |             m_vars.append(p.free_vars()); | ||||||
|             if (q != p)  |             if (q != p)  | ||||||
|  | @ -47,10 +64,10 @@ namespace polysat { | ||||||
|                     m_vars.insert(v);             |                     m_vars.insert(v);             | ||||||
|             } |             } | ||||||
|     public: |     public: | ||||||
|         static constraint* eq(unsigned lvl, pdd const& p, u_dependency* d) {  |         static constraint* eq(unsigned lvl, pdd const& p, p_dependency_ref& d) {  | ||||||
|             return alloc(constraint, lvl, p, p, d, ckind_t::eq_t);  |             return alloc(constraint, lvl, p, p, d, ckind_t::eq_t);  | ||||||
|         } |         } | ||||||
|         static constraint* ule(unsigned lvl, pdd const& p, pdd const& q, u_dependency* d) {  |         static constraint* ule(unsigned lvl, pdd const& p, pdd const& q, p_dependency_ref& d) {  | ||||||
|             return alloc(constraint, lvl, p, q, d, ckind_t::ule_t);  |             return alloc(constraint, lvl, p, q, d, ckind_t::ule_t);  | ||||||
|         } |         } | ||||||
|         ckind_t kind() const { return m_kind; } |         ckind_t kind() const { return m_kind; } | ||||||
|  | @ -58,7 +75,7 @@ namespace polysat { | ||||||
|         pdd const &  lhs() const { return m_poly; } |         pdd const &  lhs() const { return m_poly; } | ||||||
|         pdd const &  rhs() const { return m_other; } |         pdd const &  rhs() const { return m_other; } | ||||||
|         std::ostream& display(std::ostream& out) const; |         std::ostream& display(std::ostream& out) const; | ||||||
|         u_dependency* dep() const { return m_dep; } |         p_dependency* dep() const { return m_dep; } | ||||||
|         unsigned_vector& vars() { return m_vars; } |         unsigned_vector& vars() { return m_vars; } | ||||||
|         unsigned level() const { return m_level; } |         unsigned level() const { return m_level; } | ||||||
|     }; |     }; | ||||||
|  | @ -97,7 +114,10 @@ namespace polysat { | ||||||
|         trail_stack&             m_trail; |         trail_stack&             m_trail; | ||||||
|         scoped_ptr_vector<dd::pdd_manager> m_pdd; |         scoped_ptr_vector<dd::pdd_manager> m_pdd; | ||||||
|         dd::bdd_manager          m_bdd; |         dd::bdd_manager          m_bdd; | ||||||
|         u_dependency_manager     m_dep_manager; |         dep_value_manager        m_value_manager; | ||||||
|  |         small_object_allocator   m_alloc; | ||||||
|  |         poly_dep_manager         m_dep_manager; | ||||||
|  |         p_dependency_ref         m_lemma_dep; | ||||||
|         var_queue                m_free_vars; |         var_queue                m_free_vars; | ||||||
| 
 | 
 | ||||||
|         // Per constraint state
 |         // Per constraint state
 | ||||||
|  | @ -106,7 +126,7 @@ namespace polysat { | ||||||
| 
 | 
 | ||||||
|         // Per variable information
 |         // Per variable information
 | ||||||
|         vector<bdd>              m_viable;   // set of viable values.
 |         vector<bdd>              m_viable;   // set of viable values.
 | ||||||
|         ptr_vector<u_dependency> m_vdeps;    // dependencies for viable values
 |         ptr_vector<p_dependency> m_vdeps;    // dependencies for viable values
 | ||||||
|         vector<rational>         m_value;    // assigned value
 |         vector<rational>         m_value;    // assigned value
 | ||||||
|         vector<justification>    m_justification; // justification for variable assignment
 |         vector<justification>    m_justification; // justification for variable assignment
 | ||||||
|         vector<constraints>      m_cjust;    // constraints used for justification
 |         vector<constraints>      m_cjust;    // constraints used for justification
 | ||||||
|  | @ -132,6 +152,20 @@ namespace polysat { | ||||||
|          */ |          */ | ||||||
|         bool is_viable(unsigned var, rational const& val); |         bool is_viable(unsigned var, rational const& val); | ||||||
| 
 | 
 | ||||||
|  |         /**
 | ||||||
|  |          * register that val is non-viable for var. | ||||||
|  |          */ | ||||||
|  |         void add_non_viable(unsigned var, rational const& val); | ||||||
|  | 
 | ||||||
|  |          | ||||||
|  |         /**
 | ||||||
|  |          * Find a next viable value for varible. | ||||||
|  |          * l_false - there are no viable values. | ||||||
|  |          * l_true  - there is only one viable value left. | ||||||
|  |          * l_undef - there are multiple viable values, return a guess | ||||||
|  |          */ | ||||||
|  |         lbool find_viable(unsigned var, rational & val); | ||||||
|  | 
 | ||||||
|         /**
 |         /**
 | ||||||
|          * undo trail operations for backtracking. |          * undo trail operations for backtracking. | ||||||
|          * Each struct is a subclass of trail and implements undo(). |          * Each struct is a subclass of trail and implements undo(). | ||||||
|  | @ -169,7 +203,6 @@ namespace polysat { | ||||||
|         void set_mark(unsigned v) { m_marks[v] = m_clock; } |         void set_mark(unsigned v) { m_marks[v] = m_clock; } | ||||||
| 
 | 
 | ||||||
|         unsigned                 m_lemma_level { 0 }; |         unsigned                 m_lemma_level { 0 }; | ||||||
|         ptr_vector<u_dependency> m_lemma_deps; |  | ||||||
| 
 | 
 | ||||||
|         pdd isolate(unsigned v); |         pdd isolate(unsigned v); | ||||||
|         pdd resolve(unsigned v, pdd const& p, unsigned& resolve_level); |         pdd resolve(unsigned v, pdd const& p, unsigned& resolve_level); | ||||||
|  |  | ||||||
|  | @ -107,11 +107,8 @@ private: | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void unmark_todo() { |     void unmark_todo() { | ||||||
|         typename ptr_vector<dependency>::iterator it  = m_todo.begin(); |         for (auto* d : m_todo)  | ||||||
|         typename ptr_vector<dependency>::iterator end = m_todo.end(); |             d->unmark(); | ||||||
|         for (; it != end; ++it) { |  | ||||||
|             (*it)->unmark(); |  | ||||||
|         } |  | ||||||
|         m_todo.reset(); |         m_todo.reset(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -193,14 +190,10 @@ public: | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void linearize(dependency * d, vector<value, false> & vs) { |     void linearize(vector<value, false>& vs) { | ||||||
|         if (d) { |  | ||||||
|             m_todo.reset(); |  | ||||||
|             d->mark(); |  | ||||||
|             m_todo.push_back(d); |  | ||||||
|         unsigned qhead = 0; |         unsigned qhead = 0; | ||||||
|         while (qhead < m_todo.size()) { |         while (qhead < m_todo.size()) { | ||||||
|                 d = m_todo[qhead]; |             dependency * d = m_todo[qhead]; | ||||||
|             qhead++; |             qhead++; | ||||||
|             if (d->is_leaf()) { |             if (d->is_leaf()) { | ||||||
|                 vs.push_back(to_leaf(d)->m_value); |                 vs.push_back(to_leaf(d)->m_value); | ||||||
|  | @ -217,6 +210,27 @@ public: | ||||||
|         } |         } | ||||||
|         unmark_todo(); |         unmark_todo(); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     void linearize(dependency * d, vector<value, false> & vs) { | ||||||
|  |         if (!d)  | ||||||
|  |             return; | ||||||
|  |         m_todo.reset(); | ||||||
|  |         d->mark(); | ||||||
|  |         m_todo.push_back(d); | ||||||
|  |         linearize(vs); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void linearize(ptr_vector<dependency>& deps, vector<value, false> & vs) { | ||||||
|  |         if (deps.empty()) | ||||||
|  |             return; | ||||||
|  |         m_todo.reset(); | ||||||
|  |         for (auto* d : deps) { | ||||||
|  |             if (d && !d->is_marked()) { | ||||||
|  |                 d->mark(); | ||||||
|  |                 m_todo.push_back(d); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         linearize(vs); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -304,6 +318,10 @@ public: | ||||||
|         return m_dep_manager.linearize(d, vs); |         return m_dep_manager.linearize(d, vs); | ||||||
|     }     |     }     | ||||||
| 
 | 
 | ||||||
|  |     void linearize(ptr_vector<dependency>& d, vector<value, false> & vs) { | ||||||
|  |         return m_dep_manager.linearize(d, vs); | ||||||
|  |     }     | ||||||
|  |      | ||||||
|     void reset() { |     void reset() { | ||||||
|         m_allocator.reset(); |         m_allocator.reset(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue