mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	call m_egraph.merge() at a single point
This commit is contained in:
		
							parent
							
								
									d36262d731
								
							
						
					
					
						commit
						036a3f31ca
					
				
					 2 changed files with 27 additions and 20 deletions
				
			
		| 
						 | 
				
			
			@ -211,7 +211,8 @@ namespace polysat {
 | 
			
		|||
            case trail_item::mk_concat:
 | 
			
		||||
                num_replay_concat++;
 | 
			
		||||
                break;
 | 
			
		||||
            default: UNREACHABLE();
 | 
			
		||||
            default:
 | 
			
		||||
                UNREACHABLE();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        m_egraph.pop(num_scopes);
 | 
			
		||||
| 
						 | 
				
			
			@ -247,9 +248,9 @@ namespace polysat {
 | 
			
		|||
                replay_concat(ci.num_args, &m_concat_args[ci.args_idx], ci.v);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: UNREACHABLE();
 | 
			
		||||
            default:
 | 
			
		||||
                UNREACHABLE();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        m_concat_trail.shrink(m_concat_trail.size() - num_replay_concat);
 | 
			
		||||
        m_concat_args.shrink(m_concat_trail.empty() ? 0 : m_concat_trail.back().next_args_idx());
 | 
			
		||||
| 
						 | 
				
			
			@ -319,7 +320,7 @@ namespace polysat {
 | 
			
		|||
        slice_info& concat_info = m_info[concat->get_id()];
 | 
			
		||||
        SASSERT(!concat_info.slice);  // not yet set
 | 
			
		||||
        concat_info.slice = s;
 | 
			
		||||
        m_egraph.merge(s, concat, dep_t().encode());
 | 
			
		||||
        egraph_merge(s, concat, dep_t());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void slicing::add_var_congruence(pvar v) {
 | 
			
		||||
| 
						 | 
				
			
			@ -342,6 +343,8 @@ namespace polysat {
 | 
			
		|||
    void slicing::update_var_congruences() {
 | 
			
		||||
        if (!use_var_congruences())
 | 
			
		||||
            return;
 | 
			
		||||
        // TODO: this is only needed once per equivalence class
 | 
			
		||||
        //          (mark root of var2slice to detect duplicates?)
 | 
			
		||||
        for (pvar v : m_needs_congruence)
 | 
			
		||||
            add_var_congruence(v);
 | 
			
		||||
        m_needs_congruence.reset();
 | 
			
		||||
| 
						 | 
				
			
			@ -410,24 +413,17 @@ namespace polysat {
 | 
			
		|||
        // split all slices in the equivalence class
 | 
			
		||||
        for (enode* n : euf::enode_class(s))
 | 
			
		||||
            split_core(n, cut);
 | 
			
		||||
        // propagate the proper equivalences
 | 
			
		||||
        // propagate equivalences to subslices
 | 
			
		||||
        for (enode* n : euf::enode_class(s)) {
 | 
			
		||||
            enode* target = n->get_target();
 | 
			
		||||
            if (!target)
 | 
			
		||||
                continue;
 | 
			
		||||
            SASSERT(!is_value(n));  // values are always roots, and target always points towards the root.
 | 
			
		||||
            euf::justification const j = n->get_justification();
 | 
			
		||||
            SASSERT(j.is_external());  // cannot be a congruence since the slice wasn't split before.
 | 
			
		||||
            void* j_hi = j.ext<void>();
 | 
			
		||||
            void* j_lo = j.ext<void>();
 | 
			
		||||
            dep_t d = dep_t::decode(j.ext<void>());
 | 
			
		||||
            if (d.is_value()) {
 | 
			
		||||
                enode* ds = get_dep_slice(d);
 | 
			
		||||
                SASSERT(ds == n || ds == target);
 | 
			
		||||
                j_hi = mk_var_dep(get_dep_var(d), sub_hi(ds), get_dep_lit(d)).encode();
 | 
			
		||||
                j_lo = mk_var_dep(get_dep_var(d), sub_lo(ds), get_dep_lit(d)).encode();
 | 
			
		||||
            }
 | 
			
		||||
            m_egraph.merge(sub_hi(n), sub_hi(target), j_hi);
 | 
			
		||||
            m_egraph.merge(sub_lo(n), sub_lo(target), j_lo);
 | 
			
		||||
            dep_t const d = dep_t::decode(j.ext<void>());
 | 
			
		||||
            egraph_merge(sub_hi(n), sub_hi(target), d);
 | 
			
		||||
            egraph_merge(sub_lo(n), sub_lo(target), d);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -837,18 +833,26 @@ namespace polysat {
 | 
			
		|||
        m_egraph.propagate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool slicing::merge_base(enode* s1, enode* s2, dep_t dep) {
 | 
			
		||||
    bool slicing::egraph_merge(enode* s1, enode* s2, dep_t dep) {
 | 
			
		||||
        SASSERT_EQ(width(s1), width(s2));
 | 
			
		||||
        SASSERT(!has_sub(s1));
 | 
			
		||||
        SASSERT(!has_sub(s2));
 | 
			
		||||
        if (dep.is_value()) {
 | 
			
		||||
            if (is_value(s1))
 | 
			
		||||
                std::swap(s1, s2);
 | 
			
		||||
            SASSERT(is_value(s2));
 | 
			
		||||
            dep = mk_var_dep(get_dep_var(dep), s1, get_dep_lit(dep));
 | 
			
		||||
            SASSERT(!is_value(s1));  // we never merge two value slices directly
 | 
			
		||||
            if (get_dep_slice(dep) != s1)
 | 
			
		||||
                dep = mk_var_dep(get_dep_var(dep), s1, get_dep_lit(dep));
 | 
			
		||||
        }
 | 
			
		||||
        m_egraph.merge(s1, s2, dep.encode());
 | 
			
		||||
        return !is_conflict();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool slicing::merge_base(enode* s1, enode* s2, dep_t dep) {
 | 
			
		||||
        SASSERT(!has_sub(s1));
 | 
			
		||||
        SASSERT(!has_sub(s2));
 | 
			
		||||
        return egraph_merge(s1, s2, dep);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool slicing::merge(enode_vector& xs, enode_vector& ys, dep_t dep) {
 | 
			
		||||
        while (!xs.empty()) {
 | 
			
		||||
            SASSERT(!ys.empty());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -192,6 +192,9 @@ namespace polysat {
 | 
			
		|||
        void egraph_on_merge(enode* root, enode* other);
 | 
			
		||||
        void egraph_on_propagate(enode* lit, enode* ante);
 | 
			
		||||
 | 
			
		||||
        // Merge slices in the e-graph.
 | 
			
		||||
        bool egraph_merge(enode* s1, enode* s2, dep_t dep);
 | 
			
		||||
 | 
			
		||||
        // Merge equivalence classes of two base slices.
 | 
			
		||||
        // Returns true if merge succeeded without conflict.
 | 
			
		||||
        [[nodiscard]] bool merge_base(enode* s1, enode* s2, dep_t dep);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue