mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Merge branch 'master' into heap
This commit is contained in:
		
						commit
						d5c0ae7bea
					
				
					 15 changed files with 297 additions and 127 deletions
				
			
		
							
								
								
									
										2
									
								
								.github/workflows/coverage.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/coverage.yml
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -3,6 +3,8 @@ name: Code Coverage
 | 
				
			||||||
on:
 | 
					on:
 | 
				
			||||||
  push:
 | 
					  push:
 | 
				
			||||||
    branches: [ master ]
 | 
					    branches: [ master ]
 | 
				
			||||||
 | 
					  pull_request:
 | 
				
			||||||
 | 
					    branches: [ master ]
 | 
				
			||||||
  schedule:
 | 
					  schedule:
 | 
				
			||||||
    - cron: "0 11 * * *"
 | 
					    - cron: "0 11 * * *"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								.github/workflows/docker-image.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/docker-image.yml
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -41,7 +41,7 @@ jobs:
 | 
				
			||||||
            type=edge
 | 
					            type=edge
 | 
				
			||||||
            type=sha,prefix=ubuntu-20.04-bare-z3-sha-
 | 
					            type=sha,prefix=ubuntu-20.04-bare-z3-sha-
 | 
				
			||||||
      - name: Build and push Bare Z3 Docker Image
 | 
					      - name: Build and push Bare Z3 Docker Image
 | 
				
			||||||
        uses: docker/build-push-action@v6.4.0
 | 
					        uses: docker/build-push-action@v6.5.0
 | 
				
			||||||
        with:  
 | 
					        with:  
 | 
				
			||||||
          context: .
 | 
					          context: .
 | 
				
			||||||
          push: true
 | 
					          push: true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1412,8 +1412,10 @@ class HTMLFormatter(Formatter):
 | 
				
			||||||
        ys_pp = group(seq(ys))
 | 
					        ys_pp = group(seq(ys))
 | 
				
			||||||
        if a.is_forall():
 | 
					        if a.is_forall():
 | 
				
			||||||
            header = "∀"
 | 
					            header = "∀"
 | 
				
			||||||
        else:
 | 
					        elif a.is_exists():
 | 
				
			||||||
            header = "∃"
 | 
					            header = "∃"
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            header = "λ"
 | 
				
			||||||
        return group(compose(to_format(header, 1),
 | 
					        return group(compose(to_format(header, 1),
 | 
				
			||||||
                             indent(1, compose(ys_pp, to_format(" :"), line_break(), body_pp))))
 | 
					                             indent(1, compose(ys_pp, to_format(" :"), line_break(), body_pp))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -226,11 +226,27 @@ namespace datatype {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void plugin::finalize() {
 | 
					        void plugin::finalize() {
 | 
				
			||||||
            for (auto& kv : m_defs) {
 | 
					            for (auto& kv : m_defs) 
 | 
				
			||||||
                dealloc(kv.m_value);            
 | 
					                dealloc(kv.m_value);            
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            m_defs.reset();
 | 
					            m_defs.reset();
 | 
				
			||||||
            m_util = nullptr; // force deletion
 | 
					            m_util = nullptr; // force deletion
 | 
				
			||||||
 | 
					            reset();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void plugin::reset() {
 | 
				
			||||||
 | 
					            m_datatype2constructors.reset();
 | 
				
			||||||
 | 
					            m_datatype2nonrec_constructor.reset();
 | 
				
			||||||
 | 
					            m_constructor2accessors.reset();
 | 
				
			||||||
 | 
					            m_constructor2recognizer.reset();
 | 
				
			||||||
 | 
					            m_recognizer2constructor.reset();
 | 
				
			||||||
 | 
					            m_accessor2constructor.reset();
 | 
				
			||||||
 | 
					            m_is_recursive.reset();
 | 
				
			||||||
 | 
					            m_is_enum.reset();
 | 
				
			||||||
 | 
					            std::for_each(m_vectors.begin(), m_vectors.end(), delete_proc<ptr_vector<func_decl> >());
 | 
				
			||||||
 | 
					            m_vectors.reset();
 | 
				
			||||||
 | 
					            dealloc(m_asts);
 | 
				
			||||||
 | 
					            m_asts = nullptr;
 | 
				
			||||||
 | 
					            ++m_start;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        util & plugin::u() const {
 | 
					        util & plugin::u() const {
 | 
				
			||||||
| 
						 | 
					@ -578,6 +594,7 @@ namespace datatype {
 | 
				
			||||||
            if (m_defs.find(s, d)) 
 | 
					            if (m_defs.find(s, d)) 
 | 
				
			||||||
                dealloc(d);
 | 
					                dealloc(d);
 | 
				
			||||||
            m_defs.remove(s);
 | 
					            m_defs.remove(s);
 | 
				
			||||||
 | 
					            reset();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool plugin::is_value_visit(bool unique, expr * arg, ptr_buffer<app> & todo) const {
 | 
					        bool plugin::is_value_visit(bool unique, expr * arg, ptr_buffer<app> & todo) const {
 | 
				
			||||||
| 
						 | 
					@ -799,7 +816,7 @@ namespace datatype {
 | 
				
			||||||
            for (unsigned i = 0; i < n; ++i) {
 | 
					            for (unsigned i = 0; i < n; ++i) {
 | 
				
			||||||
                sort* ps = get_datatype_parameter_sort(s, i);
 | 
					                sort* ps = get_datatype_parameter_sort(s, i);
 | 
				
			||||||
                sz = get_sort_size(params, ps);
 | 
					                sz = get_sort_size(params, ps);
 | 
				
			||||||
                m_refs.push_back(sz);
 | 
					                plugin().m_refs.push_back(sz);
 | 
				
			||||||
                S.insert(d.params().get(i), sz); 
 | 
					                S.insert(d.params().get(i), sz); 
 | 
				
			||||||
            }            
 | 
					            }            
 | 
				
			||||||
            auto ss = d.sort_size();
 | 
					            auto ss = d.sort_size();
 | 
				
			||||||
| 
						 | 
					@ -896,7 +913,7 @@ namespace datatype {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            TRACE("datatype", tout << "set sort size " << s << "\n";);
 | 
					            TRACE("datatype", tout << "set sort size " << s << "\n";);
 | 
				
			||||||
            d.set_sort_size(param_size::size::mk_plus(s_add));
 | 
					            d.set_sort_size(param_size::size::mk_plus(s_add));
 | 
				
			||||||
            m_refs.reset();
 | 
					            plugin().m_refs.reset();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					@ -1008,9 +1025,7 @@ namespace datatype {
 | 
				
			||||||
    util::util(ast_manager & m):
 | 
					    util::util(ast_manager & m):
 | 
				
			||||||
        m(m),
 | 
					        m(m),
 | 
				
			||||||
        m_family_id(null_family_id),
 | 
					        m_family_id(null_family_id),
 | 
				
			||||||
        m_plugin(nullptr),
 | 
					        m_plugin(nullptr) {
 | 
				
			||||||
        m_asts(m),
 | 
					 | 
				
			||||||
        m_start(0) {
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1027,24 +1042,24 @@ namespace datatype {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    util::~util() {
 | 
					    util::~util() {
 | 
				
			||||||
        std::for_each(m_vectors.begin(), m_vectors.end(), delete_proc<ptr_vector<func_decl> >());
 | 
					        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ptr_vector<func_decl> const * util::get_datatype_constructors(sort * ty) {
 | 
					    ptr_vector<func_decl> const * util::get_datatype_constructors(sort * ty) {
 | 
				
			||||||
        SASSERT(is_datatype(ty));
 | 
					        SASSERT(is_datatype(ty));
 | 
				
			||||||
        ptr_vector<func_decl> * r = nullptr;
 | 
					        ptr_vector<func_decl> * r = nullptr;
 | 
				
			||||||
        if (m_datatype2constructors.find(ty, r))
 | 
					        if (plugin().m_datatype2constructors.find(ty, r))
 | 
				
			||||||
            return r;
 | 
					            return r;
 | 
				
			||||||
        r = alloc(ptr_vector<func_decl>);
 | 
					        r = alloc(ptr_vector<func_decl>);
 | 
				
			||||||
        m_asts.push_back(ty);
 | 
					        plugin().add_ast(ty);
 | 
				
			||||||
        m_vectors.push_back(r);
 | 
					        plugin().m_vectors.push_back(r);
 | 
				
			||||||
        m_datatype2constructors.insert(ty, r);
 | 
					        plugin().m_datatype2constructors.insert(ty, r);
 | 
				
			||||||
        if (!is_declared(ty)) 
 | 
					        if (!is_declared(ty)) 
 | 
				
			||||||
            m.raise_exception("datatype constructors have not been created");
 | 
					            m.raise_exception("datatype constructors have not been created");
 | 
				
			||||||
        def const& d = get_def(ty);
 | 
					        def const& d = get_def(ty);
 | 
				
			||||||
        for (constructor const* c : d) {
 | 
					        for (constructor const* c : d) {
 | 
				
			||||||
            func_decl_ref f = c->instantiate(ty);
 | 
					            func_decl_ref f = c->instantiate(ty);
 | 
				
			||||||
            m_asts.push_back(f);
 | 
					            plugin().add_ast(f);
 | 
				
			||||||
            r->push_back(f);
 | 
					            r->push_back(f);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return r;
 | 
					        return r;
 | 
				
			||||||
| 
						 | 
					@ -1053,13 +1068,13 @@ namespace datatype {
 | 
				
			||||||
    ptr_vector<func_decl> const * util::get_constructor_accessors(func_decl * con) {
 | 
					    ptr_vector<func_decl> const * util::get_constructor_accessors(func_decl * con) {
 | 
				
			||||||
        SASSERT(is_constructor(con));
 | 
					        SASSERT(is_constructor(con));
 | 
				
			||||||
        ptr_vector<func_decl> * res = nullptr;
 | 
					        ptr_vector<func_decl> * res = nullptr;
 | 
				
			||||||
        if (m_constructor2accessors.find(con, res)) {
 | 
					        if (plugin().m_constructor2accessors.find(con, res)) {
 | 
				
			||||||
            return res;
 | 
					            return res;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        res = alloc(ptr_vector<func_decl>);
 | 
					        res = alloc(ptr_vector<func_decl>);
 | 
				
			||||||
        m_asts.push_back(con);
 | 
					        plugin().add_ast(con);
 | 
				
			||||||
        m_vectors.push_back(res);
 | 
					        plugin().m_vectors.push_back(res);
 | 
				
			||||||
        m_constructor2accessors.insert(con, res);
 | 
					        plugin().m_constructor2accessors.insert(con, res);
 | 
				
			||||||
        sort * datatype = con->get_range();
 | 
					        sort * datatype = con->get_range();
 | 
				
			||||||
        def const& d = get_def(datatype);
 | 
					        def const& d = get_def(datatype);
 | 
				
			||||||
        for (constructor const* c : d) {
 | 
					        for (constructor const* c : d) {
 | 
				
			||||||
| 
						 | 
					@ -1067,7 +1082,7 @@ namespace datatype {
 | 
				
			||||||
                for (accessor const* a : *c) {
 | 
					                for (accessor const* a : *c) {
 | 
				
			||||||
                    func_decl_ref fn = a->instantiate(datatype);
 | 
					                    func_decl_ref fn = a->instantiate(datatype);
 | 
				
			||||||
                    res->push_back(fn);
 | 
					                    res->push_back(fn);
 | 
				
			||||||
                    m_asts.push_back(fn);
 | 
					                    plugin().add_ast(fn);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1086,7 +1101,7 @@ namespace datatype {
 | 
				
			||||||
    func_decl * util::get_constructor_recognizer(func_decl * con) {
 | 
					    func_decl * util::get_constructor_recognizer(func_decl * con) {
 | 
				
			||||||
        SASSERT(is_constructor(con));
 | 
					        SASSERT(is_constructor(con));
 | 
				
			||||||
        func_decl * d = nullptr;
 | 
					        func_decl * d = nullptr;
 | 
				
			||||||
        if (m_constructor2recognizer.find(con, d))
 | 
					        if (plugin().m_constructor2recognizer.find(con, d))
 | 
				
			||||||
            return d;
 | 
					            return d;
 | 
				
			||||||
        sort * datatype = con->get_range();
 | 
					        sort * datatype = con->get_range();
 | 
				
			||||||
        def const& dd = get_def(datatype);
 | 
					        def const& dd = get_def(datatype);
 | 
				
			||||||
| 
						 | 
					@ -1097,9 +1112,9 @@ namespace datatype {
 | 
				
			||||||
        parameter ps[2] = { parameter(con), parameter(r) };
 | 
					        parameter ps[2] = { parameter(con), parameter(r) };
 | 
				
			||||||
        d  = m.mk_func_decl(fid(), OP_DT_RECOGNISER, 2, ps, 1, &datatype);
 | 
					        d  = m.mk_func_decl(fid(), OP_DT_RECOGNISER, 2, ps, 1, &datatype);
 | 
				
			||||||
        SASSERT(d);
 | 
					        SASSERT(d);
 | 
				
			||||||
        m_asts.push_back(con);
 | 
					        plugin().add_ast(con);
 | 
				
			||||||
        m_asts.push_back(d);
 | 
					        plugin().add_ast(d);
 | 
				
			||||||
        m_constructor2recognizer.insert(con, d);
 | 
					        plugin().m_constructor2recognizer.insert(con, d);
 | 
				
			||||||
        return d;
 | 
					        return d;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1120,10 +1135,10 @@ namespace datatype {
 | 
				
			||||||
    bool util::is_recursive(sort * ty) {
 | 
					    bool util::is_recursive(sort * ty) {
 | 
				
			||||||
        SASSERT(is_datatype(ty));
 | 
					        SASSERT(is_datatype(ty));
 | 
				
			||||||
        bool r = false;
 | 
					        bool r = false;
 | 
				
			||||||
        if (!m_is_recursive.find(ty, r)) {
 | 
					        if (!plugin().m_is_recursive.find(ty, r)) {
 | 
				
			||||||
            r = is_recursive_core(ty);
 | 
					            r = is_recursive_core(ty);
 | 
				
			||||||
            m_is_recursive.insert(ty, r);
 | 
					            plugin().m_is_recursive.insert(ty, r);
 | 
				
			||||||
            m_asts.push_back(ty);
 | 
					            plugin().add_ast(ty);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return r;
 | 
					        return r;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -1147,21 +1162,21 @@ namespace datatype {
 | 
				
			||||||
        if (!is_datatype(s)) 
 | 
					        if (!is_datatype(s)) 
 | 
				
			||||||
            return false;        
 | 
					            return false;        
 | 
				
			||||||
        bool r = false;
 | 
					        bool r = false;
 | 
				
			||||||
        if (m_is_enum.find(s, r))
 | 
					        if (plugin().m_is_enum.find(s, r))
 | 
				
			||||||
            return r;
 | 
					            return r;
 | 
				
			||||||
        ptr_vector<func_decl> const& cnstrs = *get_datatype_constructors(s);
 | 
					        ptr_vector<func_decl> const& cnstrs = *get_datatype_constructors(s);
 | 
				
			||||||
        r = true;
 | 
					        r = true;
 | 
				
			||||||
        for (unsigned i = 0; r && i < cnstrs.size(); ++i) 
 | 
					        for (unsigned i = 0; r && i < cnstrs.size(); ++i) 
 | 
				
			||||||
            r = cnstrs[i]->get_arity() == 0;        
 | 
					            r = cnstrs[i]->get_arity() == 0;        
 | 
				
			||||||
        m_is_enum.insert(s, r);
 | 
					        plugin().m_is_enum.insert(s, r);
 | 
				
			||||||
        m_asts.push_back(s);
 | 
					        plugin().add_ast(s);
 | 
				
			||||||
        return r;
 | 
					        return r;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    func_decl * util::get_accessor_constructor(func_decl * accessor) { 
 | 
					    func_decl * util::get_accessor_constructor(func_decl * accessor) { 
 | 
				
			||||||
        SASSERT(is_accessor(accessor));
 | 
					        SASSERT(is_accessor(accessor));
 | 
				
			||||||
        func_decl * r = nullptr;
 | 
					        func_decl * r = nullptr;
 | 
				
			||||||
        if (m_accessor2constructor.find(accessor, r))
 | 
					        if (plugin().m_accessor2constructor.find(accessor, r))
 | 
				
			||||||
            return r;
 | 
					            return r;
 | 
				
			||||||
        sort * datatype = accessor->get_domain(0);
 | 
					        sort * datatype = accessor->get_domain(0);
 | 
				
			||||||
        symbol c_id   = accessor->get_parameter(1).get_symbol();
 | 
					        symbol c_id   = accessor->get_parameter(1).get_symbol();
 | 
				
			||||||
| 
						 | 
					@ -1174,26 +1189,15 @@ namespace datatype {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        r = fn;
 | 
					        r = fn;
 | 
				
			||||||
        m_accessor2constructor.insert(accessor, r);
 | 
					        plugin().m_accessor2constructor.insert(accessor, r);
 | 
				
			||||||
        m_asts.push_back(accessor);
 | 
					        plugin().add_ast(accessor);
 | 
				
			||||||
        m_asts.push_back(r);
 | 
					        plugin().add_ast(r);
 | 
				
			||||||
        return r;
 | 
					        return r;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void util::reset() {
 | 
					    void util::reset() {
 | 
				
			||||||
        m_datatype2constructors.reset();
 | 
					        plugin().reset();
 | 
				
			||||||
        m_datatype2nonrec_constructor.reset();
 | 
					 | 
				
			||||||
        m_constructor2accessors.reset();
 | 
					 | 
				
			||||||
        m_constructor2recognizer.reset();
 | 
					 | 
				
			||||||
        m_recognizer2constructor.reset();
 | 
					 | 
				
			||||||
        m_accessor2constructor.reset();
 | 
					 | 
				
			||||||
        m_is_recursive.reset();
 | 
					 | 
				
			||||||
        m_is_enum.reset();
 | 
					 | 
				
			||||||
        std::for_each(m_vectors.begin(), m_vectors.end(), delete_proc<ptr_vector<func_decl> >());
 | 
					 | 
				
			||||||
        m_vectors.reset();
 | 
					 | 
				
			||||||
        m_asts.reset();
 | 
					 | 
				
			||||||
        ++m_start;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1205,7 +1209,7 @@ namespace datatype {
 | 
				
			||||||
    func_decl * util::get_non_rec_constructor(sort * ty) {
 | 
					    func_decl * util::get_non_rec_constructor(sort * ty) {
 | 
				
			||||||
        SASSERT(is_datatype(ty));
 | 
					        SASSERT(is_datatype(ty));
 | 
				
			||||||
        cnstr_depth cd;
 | 
					        cnstr_depth cd;
 | 
				
			||||||
        if (m_datatype2nonrec_constructor.find(ty, cd))
 | 
					        if (plugin().m_datatype2nonrec_constructor.find(ty, cd))
 | 
				
			||||||
            return cd.first;
 | 
					            return cd.first;
 | 
				
			||||||
        ptr_vector<sort> forbidden_set;
 | 
					        ptr_vector<sort> forbidden_set;
 | 
				
			||||||
        forbidden_set.push_back(ty);
 | 
					        forbidden_set.push_back(ty);
 | 
				
			||||||
| 
						 | 
					@ -1222,7 +1226,7 @@ namespace datatype {
 | 
				
			||||||
       each T_i is not a datatype or it is a datatype t not in forbidden_set,
 | 
					       each T_i is not a datatype or it is a datatype t not in forbidden_set,
 | 
				
			||||||
       and get_non_rec_constructor_core(T_i, forbidden_set union { T_i })
 | 
					       and get_non_rec_constructor_core(T_i, forbidden_set union { T_i })
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    util::cnstr_depth util::get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set) {
 | 
					    cnstr_depth util::get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set) {
 | 
				
			||||||
        // We must select a constructor c(T_1, ..., T_n):T such that
 | 
					        // We must select a constructor c(T_1, ..., T_n):T such that
 | 
				
			||||||
        //   1) T_i's are not recursive
 | 
					        //   1) T_i's are not recursive
 | 
				
			||||||
        // If there is no such constructor, then we select one that 
 | 
					        // If there is no such constructor, then we select one that 
 | 
				
			||||||
| 
						 | 
					@ -1231,7 +1235,7 @@ namespace datatype {
 | 
				
			||||||
        ptr_vector<func_decl> const& constructors = *get_datatype_constructors(ty);
 | 
					        ptr_vector<func_decl> const& constructors = *get_datatype_constructors(ty);
 | 
				
			||||||
        array_util autil(m);
 | 
					        array_util autil(m);
 | 
				
			||||||
        cnstr_depth result(nullptr, 0);
 | 
					        cnstr_depth result(nullptr, 0);
 | 
				
			||||||
        if (m_datatype2nonrec_constructor.find(ty, result))
 | 
					        if (plugin().m_datatype2nonrec_constructor.find(ty, result))
 | 
				
			||||||
            return result;
 | 
					            return result;
 | 
				
			||||||
        TRACE("util_bug", tout << "get-non-rec constructor: " << sort_ref(ty, m) << "\n";
 | 
					        TRACE("util_bug", tout << "get-non-rec constructor: " << sort_ref(ty, m) << "\n";
 | 
				
			||||||
              tout << "forbidden: ";
 | 
					              tout << "forbidden: ";
 | 
				
			||||||
| 
						 | 
					@ -1273,9 +1277,9 @@ namespace datatype {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (result.first) {
 | 
					        if (result.first) {
 | 
				
			||||||
            m_asts.push_back(result.first);
 | 
					            plugin().add_ast(result.first);
 | 
				
			||||||
            m_asts.push_back(ty);
 | 
					            plugin().add_ast(ty);
 | 
				
			||||||
            m_datatype2nonrec_constructor.insert(ty, result);
 | 
					            plugin().m_datatype2nonrec_constructor.insert(ty, result);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return result;
 | 
					        return result;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -1291,6 +1295,7 @@ namespace datatype {
 | 
				
			||||||
        IF_VERBOSE(0, verbose_stream() << f->get_name() << "\n");
 | 
					        IF_VERBOSE(0, verbose_stream() << f->get_name() << "\n");
 | 
				
			||||||
        for (constructor* c : d)
 | 
					        for (constructor* c : d)
 | 
				
			||||||
            IF_VERBOSE(0, verbose_stream() << "!= " << c->name() << "\n");
 | 
					            IF_VERBOSE(0, verbose_stream() << "!= " << c->name() << "\n");
 | 
				
			||||||
 | 
					        return UINT_MAX;
 | 
				
			||||||
        SASSERT(false);
 | 
					        SASSERT(false);
 | 
				
			||||||
        UNREACHABLE();
 | 
					        UNREACHABLE();
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -198,6 +198,8 @@ namespace datatype {
 | 
				
			||||||
        def* translate(ast_translation& tr, util& u);
 | 
					        def* translate(ast_translation& tr, util& u);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    typedef std::pair<func_decl*, unsigned> cnstr_depth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    namespace decl {
 | 
					    namespace decl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class plugin : public decl_plugin {
 | 
					        class plugin : public decl_plugin {
 | 
				
			||||||
| 
						 | 
					@ -213,6 +215,7 @@ namespace datatype {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            void log_axiom_definitions(symbol const& s, sort * new_sort);
 | 
					            void log_axiom_definitions(symbol const& s, sort * new_sort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public:
 | 
					        public:
 | 
				
			||||||
            plugin(): m_id_counter(0), m_class_id(0), m_has_nested_rec(false) {}
 | 
					            plugin(): m_id_counter(0), m_class_id(0), m_has_nested_rec(false) {}
 | 
				
			||||||
            ~plugin() override;
 | 
					            ~plugin() override;
 | 
				
			||||||
| 
						 | 
					@ -259,6 +262,25 @@ namespace datatype {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            bool has_nested_rec() const { return m_has_nested_rec; }
 | 
					            bool has_nested_rec() const { return m_has_nested_rec; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            obj_map<sort, ptr_vector<func_decl>*>       m_datatype2constructors;
 | 
				
			||||||
 | 
					            obj_map<sort, cnstr_depth>                  m_datatype2nonrec_constructor;
 | 
				
			||||||
 | 
					            obj_map<func_decl, ptr_vector<func_decl>*>  m_constructor2accessors;
 | 
				
			||||||
 | 
					            obj_map<func_decl, func_decl*>              m_constructor2recognizer;
 | 
				
			||||||
 | 
					            obj_map<func_decl, func_decl*>              m_recognizer2constructor;
 | 
				
			||||||
 | 
					            obj_map<func_decl, func_decl*>              m_accessor2constructor;
 | 
				
			||||||
 | 
					            obj_map<sort, bool>                         m_is_recursive;
 | 
				
			||||||
 | 
					            obj_map<sort, bool>                         m_is_enum;
 | 
				
			||||||
 | 
					            mutable obj_map<sort, bool>                 m_is_fully_interp;
 | 
				
			||||||
 | 
					            mutable ast_ref_vector* m_asts = nullptr;
 | 
				
			||||||
 | 
					            sref_vector<param_size::size>               m_refs;
 | 
				
			||||||
 | 
					            ptr_vector<ptr_vector<func_decl> >          m_vectors;
 | 
				
			||||||
 | 
					            unsigned                                    m_start = 0;
 | 
				
			||||||
 | 
					            mutable ptr_vector<sort>                    m_fully_interp_trail;
 | 
				
			||||||
 | 
					            void add_ast(ast* a) const { if (!m_asts) m_asts = alloc(ast_ref_vector, *m_manager);  m_asts->push_back(a); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private:
 | 
					        private:
 | 
				
			||||||
            bool is_value_visit(bool unique, expr * arg, ptr_buffer<app> & todo) const;
 | 
					            bool is_value_visit(bool unique, expr * arg, ptr_buffer<app> & todo) const;
 | 
				
			||||||
            bool is_value_aux(bool unique, app * arg) const;
 | 
					            bool is_value_aux(bool unique, app * arg) const;
 | 
				
			||||||
| 
						 | 
					@ -295,25 +317,10 @@ namespace datatype {
 | 
				
			||||||
        ast_manager & m;
 | 
					        ast_manager & m;
 | 
				
			||||||
        mutable family_id     m_family_id;
 | 
					        mutable family_id     m_family_id;
 | 
				
			||||||
        mutable decl::plugin* m_plugin;
 | 
					        mutable decl::plugin* m_plugin;
 | 
				
			||||||
        typedef std::pair<func_decl*, unsigned> cnstr_depth;
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        family_id fid() const;
 | 
					        family_id fid() const;
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
        obj_map<sort, ptr_vector<func_decl> *>      m_datatype2constructors;
 | 
					 | 
				
			||||||
        obj_map<sort, cnstr_depth>                  m_datatype2nonrec_constructor;
 | 
					 | 
				
			||||||
        obj_map<func_decl, ptr_vector<func_decl> *> m_constructor2accessors;
 | 
					 | 
				
			||||||
        obj_map<func_decl, func_decl *>             m_constructor2recognizer;
 | 
					 | 
				
			||||||
        obj_map<func_decl, func_decl *>             m_recognizer2constructor;
 | 
					 | 
				
			||||||
        obj_map<func_decl, func_decl *>             m_accessor2constructor;
 | 
					 | 
				
			||||||
        obj_map<sort, bool>                         m_is_recursive;
 | 
					 | 
				
			||||||
        obj_map<sort, bool>                         m_is_enum;
 | 
					 | 
				
			||||||
        mutable obj_map<sort, bool>                 m_is_fully_interp;
 | 
					 | 
				
			||||||
        mutable ast_ref_vector                      m_asts;
 | 
					 | 
				
			||||||
        sref_vector<param_size::size>               m_refs;
 | 
					 | 
				
			||||||
        ptr_vector<ptr_vector<func_decl> >          m_vectors;
 | 
					 | 
				
			||||||
        unsigned                                    m_start;
 | 
					 | 
				
			||||||
        mutable ptr_vector<sort>                    m_fully_interp_trail;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        cnstr_depth get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set);
 | 
					        cnstr_depth get_non_rec_constructor_core(sort * ty, ptr_vector<sort> & forbidden_set);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        friend class decl::plugin;
 | 
					        friend class decl::plugin;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,42 +97,41 @@ public:
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct statistics {
 | 
					struct statistics {
 | 
				
			||||||
    unsigned m_make_feasible;
 | 
					    unsigned m_make_feasible = 0;
 | 
				
			||||||
    unsigned m_total_iterations;
 | 
					    unsigned m_total_iterations = 0;
 | 
				
			||||||
    unsigned m_iters_with_no_cost_growing;
 | 
					    unsigned m_iters_with_no_cost_growing = 0;
 | 
				
			||||||
    unsigned m_num_factorizations;
 | 
					    unsigned m_num_factorizations = 0;
 | 
				
			||||||
    unsigned m_num_of_implied_bounds;
 | 
					    unsigned m_num_of_implied_bounds = 0;
 | 
				
			||||||
    unsigned m_need_to_solve_inf;
 | 
					    unsigned m_need_to_solve_inf = 0;
 | 
				
			||||||
    unsigned m_max_cols;
 | 
					    unsigned m_max_cols = 0;
 | 
				
			||||||
    unsigned m_max_rows;
 | 
					    unsigned m_max_rows = 0;
 | 
				
			||||||
    unsigned m_gcd_calls;
 | 
					    unsigned m_gcd_calls = 0;
 | 
				
			||||||
    unsigned m_gcd_conflicts;
 | 
					    unsigned m_gcd_conflicts = 0;
 | 
				
			||||||
    unsigned m_cube_calls;
 | 
					    unsigned m_cube_calls = 0;
 | 
				
			||||||
    unsigned m_cube_success;
 | 
					    unsigned m_cube_success = 0;
 | 
				
			||||||
    unsigned m_patches;
 | 
					    unsigned m_patches = 0;
 | 
				
			||||||
    unsigned m_patches_success;
 | 
					    unsigned m_patches_success = 0;
 | 
				
			||||||
    unsigned m_hnf_cutter_calls;
 | 
					    unsigned m_hnf_cutter_calls = 0;
 | 
				
			||||||
    unsigned m_hnf_cuts;
 | 
					    unsigned m_hnf_cuts = 0;
 | 
				
			||||||
    unsigned m_nla_calls;
 | 
					    unsigned m_nla_calls = 0;
 | 
				
			||||||
    unsigned m_gomory_cuts;
 | 
					    unsigned m_gomory_cuts = 0;
 | 
				
			||||||
    unsigned m_nla_add_bounds;
 | 
					    unsigned m_nla_add_bounds = 0;
 | 
				
			||||||
    unsigned m_nla_propagate_bounds;
 | 
					    unsigned m_nla_propagate_bounds = 0;
 | 
				
			||||||
    unsigned m_nla_propagate_eq;
 | 
					    unsigned m_nla_propagate_eq = 0;
 | 
				
			||||||
    unsigned m_nla_lemmas;
 | 
					    unsigned m_nla_lemmas = 0;
 | 
				
			||||||
    unsigned m_nra_calls;
 | 
					    unsigned m_nra_calls = 0;
 | 
				
			||||||
    unsigned m_nla_bounds_improvements;
 | 
					    unsigned m_nla_bounds_improvements = 0;
 | 
				
			||||||
    unsigned m_horner_calls;
 | 
					    unsigned m_horner_calls = 0;
 | 
				
			||||||
    unsigned m_horner_conflicts;
 | 
					    unsigned m_horner_conflicts = 0;
 | 
				
			||||||
    unsigned m_cross_nested_forms;
 | 
					    unsigned m_cross_nested_forms = 0;
 | 
				
			||||||
    unsigned m_grobner_calls;
 | 
					    unsigned m_grobner_calls = 0;
 | 
				
			||||||
    unsigned m_grobner_conflicts;
 | 
					    unsigned m_grobner_conflicts = 0;
 | 
				
			||||||
    unsigned m_offset_eqs;
 | 
					    unsigned m_offset_eqs = 0;
 | 
				
			||||||
    unsigned m_fixed_eqs;
 | 
					    unsigned m_fixed_eqs = 0;
 | 
				
			||||||
    ::statistics m_st;
 | 
					    ::statistics m_st = {};
 | 
				
			||||||
    statistics() { reset(); }
 | 
					
 | 
				
			||||||
    void reset() {
 | 
					    void reset() {
 | 
				
			||||||
        memset(this, 0, sizeof(*this));
 | 
					        *this = statistics{};
 | 
				
			||||||
        m_st.reset();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    void collect_statistics(::statistics& st) const {
 | 
					    void collect_statistics(::statistics& st) const {
 | 
				
			||||||
        st.update("arith-factorizations", m_num_factorizations);
 | 
					        st.update("arith-factorizations", m_num_factorizations);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ public:
 | 
				
			||||||
        ref(static_matrix & m, unsigned row, unsigned col):m_matrix(m), m_row(row), m_col(col) {}
 | 
					        ref(static_matrix & m, unsigned row, unsigned col):m_matrix(m), m_row(row), m_col(col) {}
 | 
				
			||||||
        ref & operator=(T const & v) { m_matrix.set( m_row, m_col, v); return *this; }
 | 
					        ref & operator=(T const & v) { m_matrix.set( m_row, m_col, v); return *this; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ref operator=(ref & v) { m_matrix.set(m_row, m_col, v.m_matrix.get(v.m_row, v.m_col)); return *this; }
 | 
					        ref operator=(ref & v) { m_matrix.set(m_row, m_col, v.m_matrix.get_elem(v.m_row, v.m_col)); return *this; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        operator T () const { return m_matrix.get_elem(m_row, m_col); }
 | 
					        operator T () const { return m_matrix.get_elem(m_row, m_col); }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ static_matrix<T, X>::static_matrix(static_matrix const &A, unsigned * /* basis *
 | 
				
			||||||
    init_row_columns(m, m);
 | 
					    init_row_columns(m, m);
 | 
				
			||||||
    for (; m-- > 0; ) 
 | 
					    for (; m-- > 0; ) 
 | 
				
			||||||
        for (auto & col : A.m_columns[m]) 
 | 
					        for (auto & col : A.m_columns[m]) 
 | 
				
			||||||
            set(col.var(), m, A.get_value_of_column_cell(col));
 | 
					            set(col.var(), m, A.get_column_cell(col));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename T, typename X> void static_matrix<T, X>::clear() {
 | 
					template <typename T, typename X> void static_matrix<T, X>::clear() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -141,6 +141,8 @@ namespace nlsat {
 | 
				
			||||||
                auto& a = *to_ineq_atom(a1);
 | 
					                auto& a = *to_ineq_atom(a1);
 | 
				
			||||||
                if (a.size() != 2)
 | 
					                if (a.size() != 2)
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
 | 
					                if (a.is_root_atom())
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                auto* p = a.p(0);
 | 
					                auto* p = a.p(0);
 | 
				
			||||||
                auto* q = a.p(1);
 | 
					                auto* q = a.p(1);
 | 
				
			||||||
| 
						 | 
					@ -229,6 +231,10 @@ namespace nlsat {
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    SASSERT(a.is_root_atom());
 | 
				
			||||||
 | 
					                    UNREACHABLE();
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                IF_VERBOSE(3, 
 | 
					                IF_VERBOSE(3, 
 | 
				
			||||||
                s.display(verbose_stream(), c) << " ->\n";
 | 
					                s.display(verbose_stream(), c) << " ->\n";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,7 +101,7 @@ struct mbp_basic_tg::impl {
 | 
				
			||||||
                bool is_or = m.is_or(term);
 | 
					                bool is_or = m.is_or(term);
 | 
				
			||||||
                app *c = to_app(term);
 | 
					                app *c = to_app(term);
 | 
				
			||||||
                bool t = is_or ? any_of(*c, is_true) : all_of(*c, is_true);
 | 
					                bool t = is_or ? any_of(*c, is_true) : all_of(*c, is_true);
 | 
				
			||||||
                bool f = is_or ? all_of(*c, is_false) : all_of(*c, is_false);
 | 
					                bool f = is_or ? all_of(*c, is_false) : any_of(*c, is_false);
 | 
				
			||||||
                if (t || f) {
 | 
					                if (t || f) {
 | 
				
			||||||
                    mark_seen(term);
 | 
					                    mark_seen(term);
 | 
				
			||||||
                    progress = true;
 | 
					                    progress = true;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,20 @@
 | 
				
			||||||
 | 
					/*++
 | 
				
			||||||
 | 
					Copyright (c) 2024 Microsoft Corporation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Module Name:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tst_dlist.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Abstract:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Test dlist module
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Author:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Chuyue Sun 2024-07-18.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cassert>
 | 
					#include <cassert>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include "util/dlist.h"
 | 
					#include "util/dlist.h"
 | 
				
			||||||
| 
						 | 
					@ -160,10 +177,12 @@ void tst_dlist() {
 | 
				
			||||||
    test_pop();
 | 
					    test_pop();
 | 
				
			||||||
    test_insert_after();
 | 
					    test_insert_after();
 | 
				
			||||||
    test_insert_before();
 | 
					    test_insert_before();
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
    test_remove_from();
 | 
					    test_remove_from();
 | 
				
			||||||
    test_push_to_front();
 | 
					    test_push_to_front();
 | 
				
			||||||
    test_detach();
 | 
					    test_detach();
 | 
				
			||||||
    test_invariant();
 | 
					    test_invariant();
 | 
				
			||||||
    test_contains();
 | 
					    test_contains();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    std::cout << "All tests passed." << std::endl;
 | 
					    std::cout << "All tests passed." << std::endl;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@ Abstract:
 | 
				
			||||||
Author:
 | 
					Author:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Leonardo de Moura (leonardo) 2006-09-12.
 | 
					    Leonardo de Moura (leonardo) 2006-09-12.
 | 
				
			||||||
 | 
					    Chuyue Sun (liviasun) 2024-07-18.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Revision History:
 | 
					Revision History:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +21,6 @@ Revision History:
 | 
				
			||||||
#include<iostream>
 | 
					#include<iostream>
 | 
				
			||||||
#include<unordered_set>
 | 
					#include<unordered_set>
 | 
				
			||||||
#include<stdlib.h>
 | 
					#include<stdlib.h>
 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "util/hashtable.h"
 | 
					#include "util/hashtable.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,11 +119,126 @@ static void tst3() {
 | 
				
			||||||
    ENSURE(h2.size() == 2);
 | 
					    ENSURE(h2.size() == 2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Custom hash and equality functions for testing
 | 
				
			||||||
 | 
					struct my_hash {
 | 
				
			||||||
 | 
					    unsigned operator()(int x) const { return x; }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct my_eq {
 | 
				
			||||||
 | 
					    bool operator()(int x, int y) const { return x == y; }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_hashtable_constructors() {
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht;
 | 
				
			||||||
 | 
					    VERIFY(ht.empty());
 | 
				
			||||||
 | 
					    VERIFY(ht.size() == 0);
 | 
				
			||||||
 | 
					    VERIFY(ht.capacity() == DEFAULT_HASHTABLE_INITIAL_CAPACITY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Copy constructor
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht_copy(ht);
 | 
				
			||||||
 | 
					    VERIFY(ht_copy.empty());
 | 
				
			||||||
 | 
					    VERIFY(ht_copy.size() == 0);
 | 
				
			||||||
 | 
					    VERIFY(ht_copy.capacity() == ht.capacity());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Move constructor
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht_move(std::move(ht));
 | 
				
			||||||
 | 
					    VERIFY(ht_move.empty());
 | 
				
			||||||
 | 
					    VERIFY(ht_move.size() == 0);
 | 
				
			||||||
 | 
					    VERIFY(ht_move.capacity() == ht_copy.capacity());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_hashtable_insert() {
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht;
 | 
				
			||||||
 | 
					    ht.insert(1);
 | 
				
			||||||
 | 
					    VERIFY(!ht.empty());
 | 
				
			||||||
 | 
					    VERIFY(ht.size() == 1);
 | 
				
			||||||
 | 
					    int value;
 | 
				
			||||||
 | 
					    VERIFY(ht.find(1, value) && value == 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_hashtable_remove() {
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht;
 | 
				
			||||||
 | 
					    ht.insert(1);
 | 
				
			||||||
 | 
					    ht.remove(1);
 | 
				
			||||||
 | 
					    VERIFY(ht.empty());
 | 
				
			||||||
 | 
					    VERIFY(ht.size() == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_hashtable_find() {
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht;
 | 
				
			||||||
 | 
					    ht.insert(1);
 | 
				
			||||||
 | 
					    int value;
 | 
				
			||||||
 | 
					    VERIFY(ht.find(1, value) && value == 1);
 | 
				
			||||||
 | 
					    VERIFY(!ht.find(2, value));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_hashtable_contains() {
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht;
 | 
				
			||||||
 | 
					    ht.insert(1);
 | 
				
			||||||
 | 
					    VERIFY(ht.contains(1));
 | 
				
			||||||
 | 
					    VERIFY(!ht.contains(2));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_hashtable_reset() {
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht;
 | 
				
			||||||
 | 
					    ht.insert(1);
 | 
				
			||||||
 | 
					    ht.reset();
 | 
				
			||||||
 | 
					    VERIFY(ht.empty());
 | 
				
			||||||
 | 
					    VERIFY(ht.size() == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_hashtable_finalize() {
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht;
 | 
				
			||||||
 | 
					    ht.insert(1);
 | 
				
			||||||
 | 
					    ht.finalize();
 | 
				
			||||||
 | 
					    VERIFY(ht.empty());
 | 
				
			||||||
 | 
					    VERIFY(ht.size() == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_hashtable_iterators() {
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht;
 | 
				
			||||||
 | 
					    ht.insert(1);
 | 
				
			||||||
 | 
					    ht.insert(2);
 | 
				
			||||||
 | 
					    ht.insert(3);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    int count = 0;
 | 
				
			||||||
 | 
					    for(auto it = ht.begin(); it != ht.end(); ++it) {
 | 
				
			||||||
 | 
					        ++count;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    VERIFY(count == 3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_hashtable_operators() {
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht1;
 | 
				
			||||||
 | 
					    hashtable<int, my_hash, my_eq> ht2;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    ht1.insert(1);
 | 
				
			||||||
 | 
					    ht2.insert(2);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    ht1 |= ht2;
 | 
				
			||||||
 | 
					    VERIFY(ht1.contains(1));
 | 
				
			||||||
 | 
					    VERIFY(ht1.contains(2));
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    ht1 &= ht2;
 | 
				
			||||||
 | 
					    VERIFY(!ht1.contains(1));
 | 
				
			||||||
 | 
					    VERIFY(ht1.contains(2));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void tst_hashtable() {
 | 
					void tst_hashtable() {
 | 
				
			||||||
    tst3();
 | 
					    tst3();
 | 
				
			||||||
    for (int i = 0; i < 100; i++) 
 | 
					    for (int i = 0; i < 100; i++) 
 | 
				
			||||||
        tst2();
 | 
					        tst2();
 | 
				
			||||||
    tst1();
 | 
					    tst1();
 | 
				
			||||||
 | 
					    test_hashtable_constructors();
 | 
				
			||||||
 | 
					    test_hashtable_insert();
 | 
				
			||||||
 | 
					    test_hashtable_remove();
 | 
				
			||||||
 | 
					    test_hashtable_find();
 | 
				
			||||||
 | 
					    test_hashtable_contains();
 | 
				
			||||||
 | 
					    test_hashtable_reset();
 | 
				
			||||||
 | 
					    test_hashtable_finalize();
 | 
				
			||||||
 | 
					    test_hashtable_iterators();
 | 
				
			||||||
 | 
					    test_hashtable_operators();
 | 
				
			||||||
 | 
					    std::cout << "All tests passed!" << std::endl;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
void tst_hashtable() {
 | 
					void tst_hashtable() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,20 +157,12 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool invariant() const {
 | 
					    bool invariant() const {
 | 
				
			||||||
        auto* e = this;
 | 
					        auto* e = this;
 | 
				
			||||||
        const T* slow = static_cast<const T*>(this); 
 | 
					        do {
 | 
				
			||||||
        const T* fast = m_next; 
 | 
					            if (e->m_next->m_prev != e)
 | 
				
			||||||
        bool looped = false; 
 | 
					 | 
				
			||||||
        // m_next of each node should point back to m_prev of the following node,
 | 
					 | 
				
			||||||
        // and m_prev of each node should point forward to m_next of the preceding node.
 | 
					 | 
				
			||||||
        while (slow != fast) { 
 | 
					 | 
				
			||||||
            if (fast->m_prev->m_next != fast || fast->m_next->m_prev != fast) 
 | 
					 | 
				
			||||||
                return false;             
 | 
					 | 
				
			||||||
            fast = fast->m_next; 
 | 
					 | 
				
			||||||
            looped = looped || (fast == static_cast<const T*>(this)); 
 | 
					 | 
				
			||||||
            if (!looped && fast == m_next)  
 | 
					 | 
				
			||||||
                // We should be able to traverse back to the starting node. 
 | 
					 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
 | 
					            e = e->m_next;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        while (e != this);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@ Abstract:
 | 
				
			||||||
Author:
 | 
					Author:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Leonardo de Moura (leonardo) 2006-09-11.
 | 
					    Leonardo de Moura (leonardo) 2006-09-11.
 | 
				
			||||||
 | 
					    Chuyue Sun (liviasun) 2024-07-18.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Revision History:
 | 
					Revision History:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -639,6 +640,19 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef Z3DEBUG
 | 
					#ifdef Z3DEBUG
 | 
				
			||||||
    bool check_invariant() {
 | 
					    bool check_invariant() {
 | 
				
			||||||
 | 
					        // The capacity must always be a power of two.
 | 
				
			||||||
 | 
					        if (!is_power_of_two(m_capacity))
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // The number of deleted plus the size must not exceed the capacity.
 | 
				
			||||||
 | 
					        if (m_num_deleted + m_size > m_capacity)
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Checking that m_num_deleted is less than or equal to m_size.
 | 
				
			||||||
 | 
					        if (m_num_deleted > m_size) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        entry * curr = m_table;
 | 
					        entry * curr = m_table;
 | 
				
			||||||
        entry * end  = m_table + m_capacity;
 | 
					        entry * end  = m_table + m_capacity;
 | 
				
			||||||
        unsigned num_deleted = 0;
 | 
					        unsigned num_deleted = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,7 @@ void permutation::swap(unsigned i, unsigned j) noexcept {
 | 
				
			||||||
    unsigned j_prime = m_p[j];
 | 
					    unsigned j_prime = m_p[j];
 | 
				
			||||||
    std::swap(m_p[i], m_p[j]);
 | 
					    std::swap(m_p[i], m_p[j]);
 | 
				
			||||||
    std::swap(m_inv_p[i_prime], m_inv_p[j_prime]); 
 | 
					    std::swap(m_inv_p[i_prime], m_inv_p[j_prime]); 
 | 
				
			||||||
 | 
					    SASSERT(check_invariant());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -66,11 +67,19 @@ void permutation::display(std::ostream & out) const {
 | 
				
			||||||
bool permutation::check_invariant() const {
 | 
					bool permutation::check_invariant() const {
 | 
				
			||||||
    SASSERT(m_p.size() == m_inv_p.size());
 | 
					    SASSERT(m_p.size() == m_inv_p.size());
 | 
				
			||||||
    unsigned n = m_p.size();
 | 
					    unsigned n = m_p.size();
 | 
				
			||||||
 | 
					    bool_vector check_vector(n, false); // To check for duplicate and out-of-range values
 | 
				
			||||||
    for (unsigned i = 0; i < n; i++) {
 | 
					    for (unsigned i = 0; i < n; i++) {
 | 
				
			||||||
 | 
					        unsigned pi = m_p[i];
 | 
				
			||||||
        SASSERT(m_p[i] < n);
 | 
					        SASSERT(m_p[i] < n);
 | 
				
			||||||
        SASSERT(m_inv_p[i] < n);
 | 
					        SASSERT(m_inv_p[i] < n);
 | 
				
			||||||
        SASSERT(m_p[m_inv_p[i]] == i);
 | 
					        SASSERT(m_p[m_inv_p[i]] == i);
 | 
				
			||||||
        SASSERT(m_inv_p[m_p[i]] == i);
 | 
					        SASSERT(m_inv_p[m_p[i]] == i);
 | 
				
			||||||
 | 
					        // Check the inversion hasn't been checked yet
 | 
				
			||||||
 | 
					        if (check_vector[pi]) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // Mark this value as checked
 | 
				
			||||||
 | 
					        check_vector[pi] = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue