mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 11:42:28 +00:00 
			
		
		
		
	working on card
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
		
							parent
							
								
									e1640fcee9
								
							
						
					
					
						commit
						238e85867a
					
				
					 2 changed files with 185 additions and 83 deletions
				
			
		|  | @ -996,15 +996,15 @@ namespace smt { | |||
|         bool_var abv = ctx.mk_bool_var(atom); | ||||
|         ctx.set_var_theory(abv, get_id()); | ||||
|         unsigned bound = m_util.get_k(atom).get_unsigned(); | ||||
|         literal lit(abv); | ||||
| 
 | ||||
|         card* c = alloc(card, literal(abv), bound); | ||||
|         card* c = alloc(card, lit, bound); | ||||
|          | ||||
|         for (unsigned i = 0; i < num_args; ++i) { | ||||
|             expr* arg = atom->get_arg(i); | ||||
|             c->add_arg(compile_arg(arg)); | ||||
|         } | ||||
| 
 | ||||
|         literal lit(abv); | ||||
|          | ||||
|         if (c->k() == 0) { | ||||
|             ctx.mk_th_axiom(get_id(), 1, &lit); | ||||
|  | @ -1016,16 +1016,7 @@ namespace smt { | |||
|             dealloc(c); | ||||
|         } | ||||
|         else if (c->k() == c->size()) { | ||||
|             literal_vector lits; | ||||
|             for (unsigned i = 0; i < c->size(); ++i) { | ||||
|                 lits.push_back(~c->lit(i)); | ||||
|             } | ||||
|             lits.push_back(lit); | ||||
|             ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr()); | ||||
|             for (unsigned i = 0; i < c->size(); ++i) { | ||||
|                 literal lits2[2] = { ~lit, c->lit(i) }; | ||||
|                 ctx.mk_th_axiom(get_id(), 2, lits2); | ||||
|             } | ||||
|             card2conjunction(*c); | ||||
|             dealloc(c); | ||||
|         } | ||||
|         else { | ||||
|  | @ -1040,6 +1031,23 @@ namespace smt { | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     // \brief define cardinality constraint as conjunction.
 | ||||
|     // 
 | ||||
|     void theory_pb::card2conjunction(card const& c) { | ||||
|         context& ctx = get_context(); | ||||
|         literal lit = c.lit(); | ||||
|         literal_vector lits; | ||||
|         for (unsigned i = 0; i < c.size(); ++i) { | ||||
|             lits.push_back(~c.lit(i)); | ||||
|         } | ||||
|         lits.push_back(lit); | ||||
|         ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr()); | ||||
|         for (unsigned i = 0; i < c.size(); ++i) { | ||||
|             literal lits2[2] = { ~lit, c.lit(i) }; | ||||
|             ctx.mk_th_axiom(get_id(), 2, lits2); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void theory_pb::watch_literal(literal lit, card* c) { | ||||
|         init_watch(lit.var()); | ||||
|         ptr_vector<card>* cards = m_var_infos[lit.var()].m_lit_cwatch[lit.sign()]; | ||||
|  | @ -1112,9 +1120,12 @@ namespace smt { | |||
|         if (proofs_enabled()) { | ||||
|             js = alloc(theory_lemma_justification, get_id(), ctx, lits.size(), lits.c_ptr()); | ||||
|         } | ||||
|         resolve_conflict(c, lits);         | ||||
|         c.inc_propagations(*this); | ||||
|         ctx.mk_clause(lits.size(), lits.c_ptr(), js, CLS_AUX_LEMMA, 0); | ||||
|         if (!resolve_conflict(c, lits)) { | ||||
|             ctx.mk_clause(lits.size(), lits.c_ptr(), js, CLS_AUX_LEMMA, 0); | ||||
|         } | ||||
|         std::cout << "inconsistent: " << ctx.inconsistent() << "\n"; | ||||
|         SASSERT(ctx.inconsistent()); | ||||
|     } | ||||
| 
 | ||||
|     void theory_pb::add_assign(card& c, literal_vector const& lits, literal l) { | ||||
|  | @ -1938,25 +1949,24 @@ namespace smt { | |||
|     } | ||||
| 
 | ||||
|     bool theory_pb::validate_lemma() { | ||||
|         uint_set seen; | ||||
|         int value = -m_bound; | ||||
|         context& ctx = get_context(); | ||||
|         normalize_active_coeffs(); | ||||
|         for (unsigned i = 0; i < m_active_coeffs.size(); ++i) { | ||||
|             bool_var v = m_active_coeffs[i]; | ||||
|             if (seen.contains(v)) { | ||||
|                 continue; | ||||
|             } | ||||
|             seen.insert(v); | ||||
|             int coeff = get_coeff(v); | ||||
|             if (coeff == 0) continue; | ||||
|             SASSERT(coeff != 0); | ||||
|             if (coeff < 0 && ctx.get_assignment(v) != l_true) { | ||||
|                 value -= coeff; | ||||
|             } | ||||
|             else if (coeff > 0 && ctx.get_assignment(v) != l_false) { | ||||
|                 value += coeff; | ||||
|             } | ||||
|             else if (coeff == 0) { | ||||
|                 std::cout << "unexpected 0 coefficient\n"; | ||||
|             } | ||||
|         } | ||||
|         std::cout << "bound: " << m_bound << " value " << value << " lemma is " << (value >= 0 ? "sat" : "unsat") << "\n";     | ||||
|         std::cout << "bound: " << m_bound << " value " << value << " coeffs: " << m_active_coeffs.size() << " lemma is " << (value >= 0 ? "sat" : "unsat") << "\n";     | ||||
|         return value < 0; | ||||
|     } | ||||
| 
 | ||||
|  | @ -1977,18 +1987,21 @@ namespace smt { | |||
|         return arg_max; | ||||
|     } | ||||
| 
 | ||||
|     literal theory_pb::cardinality_reduction() { | ||||
|         uint_set seen; | ||||
|     literal theory_pb::cardinality_reduction(card*& c) { | ||||
|         normalize_active_coeffs(); | ||||
|         SASSERT(m_seen.empty()); | ||||
|         c = 0;         | ||||
|         int s = 0; | ||||
|         int new_bound = 0; | ||||
|         int coeff; | ||||
|         while (s < m_bound) { | ||||
|             int arg = arg_max(seen, coeff); | ||||
|             int arg = arg_max(m_seen, coeff); | ||||
|             if (arg == -1) break; | ||||
|             s += coeff; | ||||
|             ++new_bound; | ||||
|             seen.insert(arg); | ||||
|             m_seen.insert(arg); | ||||
|         } | ||||
|         m_seen.reset(); // use a trail
 | ||||
|         int slack = m_bound; | ||||
|         for (unsigned i = 0; i < m_active_coeffs.size(); ++i) { | ||||
|             coeff = get_abs_coeff(m_active_coeffs[i]); | ||||
|  | @ -2013,32 +2026,92 @@ namespace smt { | |||
|         } | ||||
|         // create cardinality constraint
 | ||||
|         literal card_lit = null_literal; | ||||
|         card* c = alloc(card, card_lit, new_bound); | ||||
|         seen.reset(); | ||||
|         for (unsigned i = 0; i < m_active_coeffs.size(); ++i) { | ||||
|             bool_var v = m_active_coeffs[i]; | ||||
|             if (seen.contains(v)) continue; | ||||
|             seen.insert(v); | ||||
|             coeff = get_coeff(v); | ||||
|             if (coeff < 0) { | ||||
|                 c->add_arg(literal(v, true)); | ||||
|                 m_coeffs[v] = -1; | ||||
|             } | ||||
|             else if (coeff > 0) { | ||||
|                 c->add_arg(literal(v, false)); | ||||
|                 m_coeffs[v] = 1; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         // display(std::cout, *c, true);
 | ||||
|         dealloc(c); | ||||
|         }         | ||||
| 
 | ||||
|         m_bound = new_bound; | ||||
|         validate_lemma(); | ||||
|         if (validate_lemma()) { | ||||
|             ast_manager& m = get_manager(); | ||||
|             context& ctx = get_context(); | ||||
|             pb_util pb(m); | ||||
|             expr_ref atom(pb.mk_fresh_bool(), m); | ||||
|             bool_var abv = ctx.mk_bool_var(atom); | ||||
|             ctx.set_var_theory(abv, get_id()); | ||||
|             card_lit = literal(abv); | ||||
|             c = alloc(card, card_lit, new_bound); | ||||
|             normalize_active_coeffs(); | ||||
|             for (unsigned i = 0; i < m_active_coeffs.size(); ++i) { | ||||
|                 bool_var v = m_active_coeffs[i]; | ||||
|                 if (coeff < 0) { | ||||
|                     c->add_arg(literal(v, true)); | ||||
|                 } | ||||
|                 else if (coeff > 0) { | ||||
|                     c->add_arg(literal(v, false)); | ||||
|                 } | ||||
|             } | ||||
|             m_stats.m_num_predicates++; | ||||
|             // display(std::cout, *c, true);
 | ||||
|             if (c->k() == 0) { | ||||
|                 UNREACHABLE(); | ||||
|             } | ||||
|             else if (c->size() < c->k()) { | ||||
|                 card_lit = false_literal; | ||||
|                 dealloc(c); | ||||
|                 c = 0; | ||||
|             } | ||||
|             else if (c->size() == c->k()) { | ||||
|                 card_lit = null_literal; | ||||
|                 unsigned lvl = UINT_MAX; | ||||
|                 for (unsigned i = 0; i < c->size(); ++i) { | ||||
|                     literal lit = c->lit(i); | ||||
|                     if (ctx.get_assignment(lit) == l_false && ctx.get_assign_level(lit) < lvl) { | ||||
|                         lvl = ctx.get_assign_level(lit); | ||||
|                         card_lit = lit; | ||||
|                     } | ||||
|                 } | ||||
|                 std::cout << "cardinality: " << card_lit << " " << atom << "\n"; | ||||
|                 dealloc(c); | ||||
|                 c = 0;                 | ||||
|             } | ||||
|             else { | ||||
|                 init_watch(abv); | ||||
|                 m_var_infos[abv].m_card = c; | ||||
|                 m_card_trail.push_back(abv); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return card_lit; | ||||
|     } | ||||
| 
 | ||||
|     void theory_pb::normalize_active_coeffs() { | ||||
|         SASSERT(m_seen.empty()); | ||||
|         unsigned i = 0, j = 0, sz = m_active_coeffs.size(); | ||||
|         for (; i < sz; ++i) { | ||||
|             bool_var v = m_active_coeffs[i]; | ||||
|             if (!m_seen.contains(v) && get_coeff(v) != 0) { | ||||
|                 m_seen.insert(v); | ||||
|                 if (j != i) { | ||||
|                     m_active_coeffs[j] = m_active_coeffs[i]; | ||||
|                 } | ||||
|                 ++j; | ||||
|             } | ||||
|         } | ||||
|         sz = j; | ||||
|         m_active_coeffs.shrink(sz); | ||||
|         for (i = 0; i < sz; ++i) { | ||||
|             m_seen.remove(m_active_coeffs[i]); | ||||
|         } | ||||
|         SASSERT(m_seen.empty()); | ||||
|     } | ||||
| 
 | ||||
|     void theory_pb::inc_coeff(literal l, int offset) {         | ||||
|         SASSERT(offset > 0); | ||||
|         bool_var v = l.var(); | ||||
|  | @ -2055,11 +2128,11 @@ namespace smt { | |||
|         int coeff1 = inc + coeff0; | ||||
|         m_coeffs[v] = coeff1; | ||||
| 
 | ||||
|         if (coeff0 > 0 && 0 > coeff1) { | ||||
|             m_bound += coeff1; | ||||
|         if (coeff0 > 0 && inc < 0) { | ||||
|             m_bound -= coeff0 - std::max(0, coeff1); | ||||
|         } | ||||
|         else if (coeff0 < 0 && 0 < coeff1) { | ||||
|             m_bound += coeff0; | ||||
|         else if (coeff0 < 0 && inc > 0) { | ||||
|             m_bound -= std::min(0, coeff1) + coeff0; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -2068,37 +2141,36 @@ namespace smt { | |||
|      */ | ||||
|     void theory_pb::cut() { | ||||
|         unsigned g = 0; | ||||
|         for (unsigned i = 0; i < m_active_coeffs.size(); ++i) { | ||||
|         for (unsigned i = 0; g != 1 && i < m_active_coeffs.size(); ++i) { | ||||
|             bool_var v = m_active_coeffs[i]; | ||||
|             int coeff = m_coeffs[v]; | ||||
|             int coeff = get_abs_coeff(v); | ||||
|             if (coeff == 0) { | ||||
|                 m_active_coeffs[i] = m_active_coeffs.back(); | ||||
|                 m_active_coeffs.pop_back(); | ||||
|                 continue; | ||||
|             } | ||||
|             if (coeff < 0) { | ||||
|                 coeff = -coeff; | ||||
|             } | ||||
|             if (m_bound < coeff) { | ||||
|                 m_coeffs[v] = m_bound; | ||||
|             if (m_bound < coeff) {                 | ||||
|                 if (get_coeff(v) > 0) { | ||||
|                     m_coeffs[v] = m_bound; | ||||
|                 } | ||||
|                 else { | ||||
|                     m_coeffs[v] = -m_bound; | ||||
|                 } | ||||
|                 coeff = m_bound; | ||||
|             } | ||||
|             SASSERT(0 < coeff && coeff <= m_bound); | ||||
|             if (g == 0) { | ||||
|                 g = static_cast<unsigned>(coeff); | ||||
|             } | ||||
|             else if (g != 1) { | ||||
|             else { | ||||
|                 g = u_gcd(g, static_cast<unsigned>(coeff)); | ||||
|             } | ||||
|         } | ||||
|         if (g != 1 && g != 0) { | ||||
|             uint_set seen; | ||||
|         if (g >= 2) { | ||||
|             normalize_active_coeffs(); | ||||
|             for (unsigned i = 0; i < m_active_coeffs.size(); ++i) { | ||||
|                 bool_var v = m_active_coeffs[i]; | ||||
|                 if (!seen.contains(v)) { | ||||
|                     seen.insert(v); | ||||
|                     m_coeffs[v] /= g; | ||||
|                 } | ||||
|                 m_coeffs[m_active_coeffs[i]] /= g;                 | ||||
|             } | ||||
|             m_bound /= g; | ||||
|             std::cout << "CUT " << g << "\n"; | ||||
|             TRACE("pb", display_resolved_lemma(tout << "cut\n");); | ||||
|         } | ||||
|     } | ||||
|  | @ -2119,6 +2191,8 @@ namespace smt { | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         std::cout << c.lit() << "\n"; | ||||
| 
 | ||||
|         reset_coeffs(); | ||||
|         m_num_marks = 0; | ||||
|         m_bound = c.k(); | ||||
|  | @ -2142,22 +2216,30 @@ namespace smt { | |||
|             v = conseq.var(); | ||||
|             TRACE("pb", display_resolved_lemma(tout << conseq << "\n");); | ||||
| 
 | ||||
|             int offset = get_coeff(v); | ||||
|             int offset = get_abs_coeff(v); | ||||
| 
 | ||||
|             if (offset == 0) { | ||||
|                 goto process_next_resolvent;             | ||||
|             } | ||||
|             else if (offset < 0) { | ||||
|                 offset = -offset; | ||||
|             SASSERT(validate_lemma()); | ||||
|             if (offset > 1000) { | ||||
|                 while (m_num_marks > 0 && idx > 0) { | ||||
|                     v = lits[idx].var(); | ||||
|                     if (ctx.is_marked(v)) { | ||||
|                         ctx.unset_mark(v); | ||||
|                     } | ||||
|                     --idx; | ||||
|                 } | ||||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
|             SASSERT(offset > 0); | ||||
| 
 | ||||
|             js = ctx.get_justification(v); | ||||
|             validate_lemma(); | ||||
|             // ctx.display(std::cout, js);
 | ||||
|              | ||||
|             inc_coeff(conseq, offset); | ||||
| 
 | ||||
|              | ||||
|             //
 | ||||
|             // Resolve selected conseq with antecedents.
 | ||||
|             // 
 | ||||
|  | @ -2167,6 +2249,7 @@ namespace smt { | |||
|             switch(js.get_kind()) { | ||||
|                  | ||||
|             case b_justification::CLAUSE: { | ||||
|                 inc_coeff(conseq, offset); | ||||
|                 clause& cls = *js.get_clause(); | ||||
|                 justification* cjs = cls.get_justification(); | ||||
|                 if (cjs && !is_proof_justification(*cjs)) { | ||||
|  | @ -2189,6 +2272,7 @@ namespace smt { | |||
|                 break;                 | ||||
|             } | ||||
|             case b_justification::BIN_CLAUSE: | ||||
|                 inc_coeff(conseq, offset); | ||||
|                 process_antecedent(~js.get_literal(), offset); | ||||
|                 TRACE("pb", tout << "binary: " << js.get_literal() << "\n";); | ||||
|                 break; | ||||
|  | @ -2204,11 +2288,17 @@ namespace smt { | |||
|                 } | ||||
|                 if (pbj == 0) { | ||||
|                     TRACE("pb", tout << "skip justification for " << conseq << "\n";); | ||||
|                     inc_coeff(conseq, offset); | ||||
|                 } | ||||
|                 else { | ||||
|                     process_card(pbj->get_card(), offset); | ||||
|                     bound = pbj->get_card().k(); | ||||
|                     card& c2 = pbj->get_card(); | ||||
|                     process_card(c2, offset); | ||||
|                     unsigned i = 0; | ||||
|                     for (i = 0; i < c2.size() && c2.lit(i) != conseq; ++i) {} | ||||
|                     std::cout << c2.lit() << " index at " << i << " of " << c2.size(); | ||||
|                     bound = c2.k(); | ||||
|                 } | ||||
|                 std::cout << " offset: " << offset << " bound: " << bound << "\n"; | ||||
|                 break; | ||||
|             } | ||||
|             default: | ||||
|  | @ -2234,36 +2324,45 @@ namespace smt { | |||
|             --idx; | ||||
|             --m_num_marks; | ||||
|         } | ||||
|         validate_lemma(); | ||||
|         SASSERT(validate_lemma()); | ||||
| 
 | ||||
|         TRACE("pb", display_resolved_lemma(tout << "done\n");); | ||||
|          | ||||
|          | ||||
|         uint_set seen; | ||||
| 
 | ||||
|         normalize_active_coeffs(); | ||||
|         int count = 0, sz = 0; | ||||
|         for (unsigned i = 0; i < m_active_coeffs.size(); ++i) { | ||||
|             bool_var v = m_active_coeffs[i]; | ||||
|             if (seen.contains(v)) { | ||||
|                 continue; | ||||
|             } | ||||
|             seen.insert(v); | ||||
|             int coeff = get_abs_coeff(v); | ||||
|             if (coeff == 0) continue; | ||||
|             SASSERT(coeff > 0); | ||||
|             ++sz; | ||||
|             count += coeff; | ||||
|         } | ||||
|         std::cout << "New " << count << "(" << sz << ") >= " << m_bound << " " << c.size() << " >= " << c.k() << " new diff: " << count - m_bound  << " old diff: " << c.size() - c.k() << "\n"; | ||||
|         literal card_lit = cardinality_reduction(); | ||||
|         card* cr = 0; | ||||
|         literal card_lit = cardinality_reduction(cr); | ||||
| 
 | ||||
|         if (card_lit != null_literal) { | ||||
|             for (unsigned i = 0; i < m_antecedents.size(); ++i) { | ||||
|                 m_antecedents[i].neg(); | ||||
|             } | ||||
|             m_antecedents.push_back(card_lit); | ||||
|             ctx.mk_clause(m_antecedents.size(), m_antecedents.c_ptr(), 0, CLS_AUX_LEMMA, 0); // TBD add delete handler to GC card closure.
 | ||||
|             ctx.assign(card_lit, ctx.mk_justification(theory_propagation_justification(get_id(), ctx.get_region(), m_antecedents.size(), m_antecedents.c_ptr(), card_lit, 0, 0))); | ||||
|         } | ||||
| 
 | ||||
|         return true;     | ||||
|         if (cr != 0) { | ||||
|             m_antecedents.reset(); | ||||
|             m_antecedents.push_back(card_lit); | ||||
|             unsigned slack = cr ? (cr->size() - cr->k()) : 0; | ||||
|             for (unsigned i = 0; 0 < slack && i < cr->size(); ++i) { | ||||
|                 literal lit = cr->lit(i); | ||||
|                 SASSERT(lit.var() != conseq.var() || lit == ~conseq); | ||||
|                 if (lit.var() != conseq.var() && ctx.get_assignment(lit) == l_false) { | ||||
|                     m_antecedents.push_back(~lit); | ||||
|                     --slack; | ||||
|                 } | ||||
|             } | ||||
|             ctx.assign(~conseq, ctx.mk_justification(theory_propagation_justification(get_id(), ctx.get_region(), m_antecedents.size(), m_antecedents.c_ptr(), ~conseq, 0, 0))); | ||||
|             std::cout << conseq << " " << ctx.get_assignment(conseq) << "\n"; | ||||
|         } | ||||
| 
 | ||||
|         return card_lit != null_literal; | ||||
|     } | ||||
| 
 | ||||
|     bool theory_pb::is_proof_justification(justification const& j) const { | ||||
|  |  | |||
|  | @ -324,6 +324,7 @@ namespace smt { | |||
|         unsigned_vector          m_card_lim; | ||||
|         bool is_cardinality_constraint(app * atom); | ||||
|         bool internalize_card(app * atom, bool gate_ctx); | ||||
|         void card2conjunction(card const& c); | ||||
| 
 | ||||
|         void watch_literal(literal lit, card* c); | ||||
|         void unwatch_literal(literal w, card* c); | ||||
|  | @ -367,20 +368,22 @@ namespace smt { | |||
|         unsigned          m_num_marks; | ||||
|         unsigned_vector   m_resolved; | ||||
|         unsigned          m_conflict_lvl; | ||||
| 
 | ||||
|         // Conflict PB constraints
 | ||||
|         svector<int>      m_coeffs; | ||||
|         svector<bool_var> m_active_coeffs; | ||||
|         int               m_bound; | ||||
|         literal_vector    m_antecedents; | ||||
|         uint_set          m_seen; | ||||
| 
 | ||||
|         void normalize_active_coeffs(); | ||||
|         void inc_coeff(literal l, int offset); | ||||
| 
 | ||||
|         int get_coeff(bool_var v) const; | ||||
|         int get_abs_coeff(bool_var v) const; | ||||
|         | ||||
|         int get_abs_coeff(bool_var v) const;        | ||||
|         int arg_max(uint_set& seen, int& coeff);  | ||||
| 
 | ||||
|         void reset_coeffs(); | ||||
|         literal cardinality_reduction(); | ||||
|         literal cardinality_reduction(card*& c); | ||||
| 
 | ||||
|         bool resolve_conflict(card& c, literal_vector const& conflict_clause); | ||||
|         void process_antecedent(literal l, int offset); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue