mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 11:42:28 +00:00 
			
		
		
		
	Parallel solving (#7758)
* very basic setup * ensure solve_eqs is fully disabled when smt.solve_eqs=false, #7743 Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * respect smt configuration parameter in elim_unconstrained simplifier Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * indentation * add bash files for test runs * add option to selectively disable variable solving for only ground expressions Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove verbose output Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix #7745 axioms for len(substr(...)) escaped due to nested rewriting * ensure atomic constraints are processed by arithmetic solver * #7739 optimization add simplification rule for at(x, offset) = "" Introducing j just postpones some rewrites that prevent useful simplifications. Z3 already uses common sub-expressions. The example highlights some opportunities for simplification, noteworthy at(..) = "". The example is solved in both versions after adding this simplification. * fix unsound len(substr) axiom Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * FreshConst is_sort (#7748) * #7750 add pre-processing simplification * Add parameter validation for selected API functions * updates to ac-plugin fix incrementality bugs by allowing destructive updates during saturation at the cost of redoing saturation after a pop. * enable passive, add check for bloom up-to-date * add top-k fixed-sized min-heap priority queue for top scoring literals * set up worker thread batch manager for multithreaded batch cubes paradigm, need to debug as I am getting segfault still * fix bug in parallel solving batch setup * fix bug * allow for internalize implies * disable pre-processing during cubing * debugging * remove default constructor * remove a bunch of string copies * Update euf_ac_plugin.cpp include reduction rules in forward simplification * Update euf_completion.cpp try out restricting scope of equalities added by instantation * Update smt_parallel.cpp Drop non-relevant units from shared structures. * process cubes as lists of individual lits * merge * Add support for Algebraic Datatypes in JavaScript/TypeScript bindings (#7734) * Initial plan * Add datatype type definitions to types.ts (work in progress) Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Complete datatype type definitions with working TypeScript compilation Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Implement core datatype functionality with TypeScript compilation success Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Complete datatype implementation with full Context integration and tests Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * chipping away at the new code structure --------- Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> Co-authored-by: Nikolaj Bjorner <nbjorner@microsoft.com> Co-authored-by: humnrdble <83878671+humnrdble@users.noreply.github.com> Co-authored-by: Nuno Lopes <nuno.lopes@tecnico.ulisboa.pt> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									0ac6abf3a8
								
							
						
					
					
						commit
						aa5d833b38
					
				
					 11 changed files with 552 additions and 469 deletions
				
			
		|  | @ -278,17 +278,9 @@ namespace euf { | |||
|         if (!m_shared.empty()) | ||||
|             out << "shared monomials:\n"; | ||||
|         for (auto const& s : m_shared) { | ||||
|             out << g.bpp(s.n) << ": " << s.m << " r: " << g.bpp(s.n->get_root()) << "\n"; | ||||
|             out << g.bpp(s.n) << " r " << g.bpp(s.n->get_root()) << " - " << s.m << ": " << m_pp_ll(*this, monomial(s.m)) << "\n"; | ||||
|         } | ||||
| #if 0 | ||||
|         i = 0; | ||||
|         for (auto m : m_monomials) { | ||||
|             out << i << ": "; | ||||
|             display_monomial_ll(out, m); | ||||
|             out << "\n"; | ||||
|             ++i; | ||||
|         } | ||||
| #endif | ||||
| 
 | ||||
|         for (auto n : m_nodes) { | ||||
|             if (!n) | ||||
|                 continue; | ||||
|  | @ -361,19 +353,16 @@ namespace euf { | |||
|         if (!orient_equation(eq)) | ||||
|             return false; | ||||
| 
 | ||||
| #if 1 | ||||
|         if (is_reducing(eq)) | ||||
|             is_active = true; | ||||
| #else | ||||
| 
 | ||||
|         is_active = true; // set to active by default
 | ||||
| #endif | ||||
| 
 | ||||
|         if (!is_active) { | ||||
|             m_passive.push_back(eq); | ||||
|             return true;           | ||||
|         } | ||||
| 
 | ||||
|         eq.status = eq_status::is_to_simplify_eq; | ||||
| 
 | ||||
|         m_active.push_back(eq); | ||||
|         auto& ml = monomial(eq.l); | ||||
|         auto& mr = monomial(eq.r); | ||||
|  | @ -621,9 +610,9 @@ namespace euf { | |||
|             // simplify eq using processed
 | ||||
|             TRACE(plugin, | ||||
|                 for (auto other_eq : forward_iterator(eq_id)) | ||||
|                     tout << "forward iterator " << eq_id << " vs " << other_eq << " " << is_processed(other_eq) << "\n"); | ||||
|                     tout << "forward iterator " << eq_pp_ll(*this, m_active[eq_id]) << " vs " << eq_pp_ll(*this, m_active[other_eq])  << "\n"); | ||||
|             for (auto other_eq : forward_iterator(eq_id)) | ||||
|                 if (is_processed(other_eq) && forward_simplify(eq_id, other_eq)) | ||||
|                 if ((is_processed(other_eq) || is_reducing(other_eq)) && forward_simplify(eq_id, other_eq)) | ||||
|                     goto loop_start; | ||||
| 
 | ||||
|             auto& eq = m_active[eq_id]; | ||||
|  | @ -914,6 +903,8 @@ namespace euf { | |||
|             set_status(dst_eq, eq_status::is_dead_eq); | ||||
|             return true; | ||||
|         } | ||||
|         SASSERT(!are_equal(m_active[src_eq], m_active[dst_eq])); | ||||
|          | ||||
|         if (!is_equation_oriented(src)) | ||||
|             return false; | ||||
|         // check that src.l is a subset of dst.r
 | ||||
|  | @ -1088,23 +1079,18 @@ namespace euf { | |||
|     // rewrite monomial to normal form.
 | ||||
|     bool ac_plugin::reduce(ptr_vector<node>& m, justification& j) { | ||||
|         bool change = false; | ||||
|         unsigned sz = m.size(); | ||||
|         do { | ||||
|         init_loop: | ||||
|             if (m.size() == 1) | ||||
|                 return change; | ||||
|             bloom b; | ||||
|             init_ref_counts(m, m_m_counts); | ||||
|             for (auto n : m) { | ||||
|                 if (n->is_zero) { | ||||
|                     m[0] = n; | ||||
|                     m.shrink(1); | ||||
|                     change = true; | ||||
|                     break; | ||||
|                 } | ||||
|                 for (auto eq : n->eqs) { | ||||
|                     continue; | ||||
|                     if (!is_reducing(eq)) // also can use processed?
 | ||||
|                         continue; | ||||
|                     auto& src = m_active[eq]; | ||||
| 
 | ||||
|                     if (!is_equation_oriented(src)) | ||||
|  | @ -1116,17 +1102,16 @@ namespace euf { | |||
| 
 | ||||
|                     TRACE(plugin, display_equation_ll(tout << "reduce ", src) << "\n"); | ||||
|                     SASSERT(is_correct_ref_count(monomial(src.l), m_eq_counts)); | ||||
|                     //display_equation_ll(std::cout << "reduce ", src) << ": ";
 | ||||
|                     //display_monomial_ll(std::cout, m);
 | ||||
|                     for (auto n : m) | ||||
|                         for (auto s : n->shared) | ||||
|                             m_shared_todo.insert(s); | ||||
|                     rewrite1(m_eq_counts, monomial(src.r), m_m_counts, m); | ||||
|                     //display_monomial_ll(std::cout << " -> ", m) << "\n";
 | ||||
|                     j = join(j, eq); | ||||
|                     change = true; | ||||
|                     goto init_loop; | ||||
|                 } | ||||
|             } | ||||
|         } while (false); | ||||
|         VERIFY(sz >= m.size()); | ||||
|         return change; | ||||
|     } | ||||
| 
 | ||||
|  | @ -1287,6 +1272,8 @@ namespace euf { | |||
|                 continue; | ||||
|             } | ||||
|             change = true; | ||||
|             for (auto s : n->shared) | ||||
|                 m_shared_todo.insert(s); | ||||
|             if (r.size() == 0) | ||||
|                 // if r is empty, we can remove n from l
 | ||||
|                 continue; | ||||
|  | @ -1407,9 +1394,11 @@ namespace euf { | |||
|         TRACE(plugin_verbose, tout << "num shared todo " << m_shared_todo.size() << "\n"); | ||||
|         if (m_shared_todo.empty()) | ||||
|             return; | ||||
| 
 | ||||
|         while (!m_shared_todo.empty()) { | ||||
|             auto idx = *m_shared_todo.begin(); | ||||
|             m_shared_todo.remove(idx); | ||||
|             m_shared_todo.remove(idx);         | ||||
|             TRACE(plugin, tout << "index " << idx << " shared size " << m_shared.size() << "\n"); | ||||
|             if (idx < m_shared.size()) | ||||
|                 simplify_shared(idx, m_shared[idx]); | ||||
|         } | ||||
|  | @ -1431,7 +1420,7 @@ namespace euf { | |||
|         auto old_m = s.m; | ||||
|         auto old_n = monomial(old_m).m_src; | ||||
|         ptr_vector<node> m1(monomial(old_m).m_nodes); | ||||
|         TRACE(plugin_verbose, tout << "simplify shared: " << g.bpp(old_n) << ": " << m_pp_ll(*this, monomial(old_m)) << "\n"); | ||||
|         TRACE(plugin, tout << "simplify shared: " << g.bpp(old_n) << ": " << m_pp_ll(*this, monomial(old_m)) << "\n"); | ||||
|         if (!reduce(m1, j)) | ||||
|             return; | ||||
| 
 | ||||
|  |  | |||
|  | @ -268,7 +268,6 @@ namespace euf { | |||
|         expr_ref r(f, m); | ||||
|         m_rewriter(r); | ||||
|         f = r.get(); | ||||
|         // verbose_stream() << r << "\n";
 | ||||
|         auto cons = m.mk_app(symbol("consequence"), 1, &f, m.mk_bool_sort()); | ||||
|         m_fmls.add(dependent_expr(m, cons, nullptr, nullptr)); | ||||
|     } | ||||
|  | @ -317,35 +316,43 @@ namespace euf { | |||
|             expr_ref y1(y, m); | ||||
|             m_rewriter(x1); | ||||
|             m_rewriter(y1); | ||||
|              | ||||
| 
 | ||||
|             add_quantifiers(x1); | ||||
|             add_quantifiers(y1); | ||||
|             enode* a = mk_enode(x1); | ||||
|             enode* b = mk_enode(y1); | ||||
| 
 | ||||
|             if (a->get_root() == b->get_root()) | ||||
|                 return;            | ||||
|             m_egraph.merge(a, b, to_ptr(push_pr_dep(pr, d))); | ||||
|             m_egraph.propagate(); | ||||
|                 return; | ||||
| 
 | ||||
|             TRACE(euf, tout << "merge and propagate\n"); | ||||
|             add_children(a); | ||||
|             add_children(b); | ||||
|             m_egraph.merge(a, b, to_ptr(push_pr_dep(pr, d))); | ||||
|             m_egraph.propagate(); | ||||
|             m_should_propagate = true;  | ||||
| 
 | ||||
| #if 0 | ||||
|             auto a1 = mk_enode(x); | ||||
|             if (a1->get_root() != a->get_root()) { | ||||
|             auto b1 = mk_enode(y); | ||||
| 
 | ||||
|             if (a->get_root() != a1->get_root()) { | ||||
|                 add_children(a1);; | ||||
|                 m_egraph.merge(a, a1, nullptr); | ||||
|                 m_egraph.propagate(); | ||||
|                 add_children(a1); | ||||
|             } | ||||
|             auto b1 = mk_enode(y); | ||||
|             if (b1->get_root() != b->get_root()) { | ||||
|                 TRACE(euf, tout << "merge and propagate\n"); | ||||
|                 m_egraph.merge(b, b1, nullptr); | ||||
|                 m_egraph.propagate(); | ||||
|                 add_children(b1); | ||||
|             } | ||||
| 
 | ||||
|             m_should_propagate = true; | ||||
|             if (m_side_condition_solver) | ||||
|             if (b->get_root() != b1->get_root()) { | ||||
|                 add_children(b1); | ||||
|                 m_egraph.merge(b, b1, nullptr); | ||||
|                 m_egraph.propagate(); | ||||
|             } | ||||
| #endif | ||||
|              | ||||
|             if (m_side_condition_solver && a->get_root() != b->get_root()) | ||||
|                 m_side_condition_solver->add_constraint(f, pr, d); | ||||
|             IF_VERBOSE(1, verbose_stream() << "eq: " << mk_pp(x1, m) << " == " << mk_pp(y1, m) << "\n"); | ||||
|             IF_VERBOSE(1, verbose_stream() << "eq: " << a->get_root_id() << " " << b->get_root_id() << " "  | ||||
|                  << x1 << " == " << y1 << "\n"); | ||||
|         } | ||||
|         else if (m.is_not(f, f)) { | ||||
|             enode* n = mk_enode(f); | ||||
|  | @ -689,7 +696,7 @@ namespace euf { | |||
|         b = new (mem) binding(q, pat, max_generation, min_top, max_top); | ||||
|         b->init(b); | ||||
|         for (unsigned i = 0; i < n; ++i) | ||||
|             b->m_nodes[i] = _binding[i]; | ||||
|             b->m_nodes[i] = _binding[i]->get_root(); | ||||
| 
 | ||||
|         m_bindings.insert(b); | ||||
|         get_trail().push(insert_map<bindings, binding*>(m_bindings, b)); | ||||
|  | @ -748,12 +755,13 @@ namespace euf { | |||
| 
 | ||||
|     void completion::apply_binding(binding& b, quantifier* q, expr_ref_vector const& s) { | ||||
|         var_subst subst(m); | ||||
|         expr_ref r = subst(q->get_expr(), s);         | ||||
|         expr_ref r = subst(q->get_expr(), s);       | ||||
|         scoped_generation sg(*this, b.m_max_top_generation + 1); | ||||
|         auto [pr, d] = get_dependency(q); | ||||
|         if (pr) | ||||
|             pr = m.mk_quant_inst(m.mk_or(m.mk_not(q), r), s.size(), s.data()); | ||||
|         m_consequences.push_back(r); | ||||
|         TRACE(euf_completion, tout << "new instantiation: " << r << " q: " << mk_pp(q, m) << "\n"); | ||||
|         add_constraint(r, pr, d); | ||||
|         propagate_rules(); | ||||
|         m_egraph.propagate(); | ||||
|  | @ -1022,7 +1030,7 @@ namespace euf { | |||
| 
 | ||||
|         } | ||||
|         enode* n = m_egraph.find(f); | ||||
|          | ||||
|         if (!n) n = mk_enode(f); | ||||
|         enode* r = n->get_root(); | ||||
|         d = m.mk_join(d, explain_eq(n, r)); | ||||
|         d = m.mk_join(d, m_deps.get(r->get_id(), nullptr)); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue