mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 19:52:29 +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: | ||||
|   push: | ||||
|     branches: [ master ] | ||||
|   pull_request: | ||||
|     branches: [ master ] | ||||
|   schedule: | ||||
|     - 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=sha,prefix=ubuntu-20.04-bare-z3-sha- | ||||
|       - 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:   | ||||
|           context: . | ||||
|           push: true | ||||
|  |  | |||
|  | @ -1412,8 +1412,10 @@ class HTMLFormatter(Formatter): | |||
|         ys_pp = group(seq(ys)) | ||||
|         if a.is_forall(): | ||||
|             header = "∀" | ||||
|         else: | ||||
|         elif a.is_exists(): | ||||
|             header = "∃" | ||||
|         else: | ||||
|             header = "λ" | ||||
|         return group(compose(to_format(header, 1), | ||||
|                              indent(1, compose(ys_pp, to_format(" :"), line_break(), body_pp)))) | ||||
| 
 | ||||
|  |  | |||
|  | @ -226,11 +226,27 @@ namespace datatype { | |||
|         } | ||||
| 
 | ||||
|         void plugin::finalize() { | ||||
|             for (auto& kv : m_defs) { | ||||
|             for (auto& kv : m_defs)  | ||||
|                 dealloc(kv.m_value);             | ||||
|             } | ||||
|             m_defs.reset(); | ||||
|             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 { | ||||
|  | @ -578,6 +594,7 @@ namespace datatype { | |||
|             if (m_defs.find(s, d))  | ||||
|                 dealloc(d); | ||||
|             m_defs.remove(s); | ||||
|             reset(); | ||||
|         } | ||||
| 
 | ||||
|         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) { | ||||
|                 sort* ps = get_datatype_parameter_sort(s, i); | ||||
|                 sz = get_sort_size(params, ps); | ||||
|                 m_refs.push_back(sz); | ||||
|                 plugin().m_refs.push_back(sz); | ||||
|                 S.insert(d.params().get(i), sz);  | ||||
|             }             | ||||
|             auto ss = d.sort_size(); | ||||
|  | @ -896,7 +913,7 @@ namespace datatype { | |||
|             } | ||||
|             TRACE("datatype", tout << "set sort size " << s << "\n";); | ||||
|             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): | ||||
|         m(m), | ||||
|         m_family_id(null_family_id), | ||||
|         m_plugin(nullptr), | ||||
|         m_asts(m), | ||||
|         m_start(0) { | ||||
|         m_plugin(nullptr) { | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1027,24 +1042,24 @@ namespace datatype { | |||
| 
 | ||||
| 
 | ||||
|     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) { | ||||
|         SASSERT(is_datatype(ty)); | ||||
|         ptr_vector<func_decl> * r = nullptr; | ||||
|         if (m_datatype2constructors.find(ty, r)) | ||||
|         if (plugin().m_datatype2constructors.find(ty, r)) | ||||
|             return r; | ||||
|         r = alloc(ptr_vector<func_decl>); | ||||
|         m_asts.push_back(ty); | ||||
|         m_vectors.push_back(r); | ||||
|         m_datatype2constructors.insert(ty, r); | ||||
|         plugin().add_ast(ty); | ||||
|         plugin().m_vectors.push_back(r); | ||||
|         plugin().m_datatype2constructors.insert(ty, r); | ||||
|         if (!is_declared(ty))  | ||||
|             m.raise_exception("datatype constructors have not been created"); | ||||
|         def const& d = get_def(ty); | ||||
|         for (constructor const* c : d) { | ||||
|             func_decl_ref f = c->instantiate(ty); | ||||
|             m_asts.push_back(f); | ||||
|             plugin().add_ast(f); | ||||
|             r->push_back(f); | ||||
|         } | ||||
|         return r; | ||||
|  | @ -1053,13 +1068,13 @@ namespace datatype { | |||
|     ptr_vector<func_decl> const * util::get_constructor_accessors(func_decl * con) { | ||||
|         SASSERT(is_constructor(con)); | ||||
|         ptr_vector<func_decl> * res = nullptr; | ||||
|         if (m_constructor2accessors.find(con, res)) { | ||||
|         if (plugin().m_constructor2accessors.find(con, res)) { | ||||
|             return res; | ||||
|         } | ||||
|         res = alloc(ptr_vector<func_decl>); | ||||
|         m_asts.push_back(con); | ||||
|         m_vectors.push_back(res); | ||||
|         m_constructor2accessors.insert(con, res); | ||||
|         plugin().add_ast(con); | ||||
|         plugin().m_vectors.push_back(res); | ||||
|         plugin().m_constructor2accessors.insert(con, res); | ||||
|         sort * datatype = con->get_range(); | ||||
|         def const& d = get_def(datatype); | ||||
|         for (constructor const* c : d) { | ||||
|  | @ -1067,7 +1082,7 @@ namespace datatype { | |||
|                 for (accessor const* a : *c) { | ||||
|                     func_decl_ref fn = a->instantiate(datatype); | ||||
|                     res->push_back(fn); | ||||
|                     m_asts.push_back(fn); | ||||
|                     plugin().add_ast(fn); | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|  | @ -1086,7 +1101,7 @@ namespace datatype { | |||
|     func_decl * util::get_constructor_recognizer(func_decl * con) { | ||||
|         SASSERT(is_constructor(con)); | ||||
|         func_decl * d = nullptr; | ||||
|         if (m_constructor2recognizer.find(con, d)) | ||||
|         if (plugin().m_constructor2recognizer.find(con, d)) | ||||
|             return d; | ||||
|         sort * datatype = con->get_range(); | ||||
|         def const& dd = get_def(datatype); | ||||
|  | @ -1097,9 +1112,9 @@ namespace datatype { | |||
|         parameter ps[2] = { parameter(con), parameter(r) }; | ||||
|         d  = m.mk_func_decl(fid(), OP_DT_RECOGNISER, 2, ps, 1, &datatype); | ||||
|         SASSERT(d); | ||||
|         m_asts.push_back(con); | ||||
|         m_asts.push_back(d); | ||||
|         m_constructor2recognizer.insert(con, d); | ||||
|         plugin().add_ast(con); | ||||
|         plugin().add_ast(d); | ||||
|         plugin().m_constructor2recognizer.insert(con, d); | ||||
|         return d; | ||||
|     } | ||||
| 
 | ||||
|  | @ -1120,10 +1135,10 @@ namespace datatype { | |||
|     bool util::is_recursive(sort * ty) { | ||||
|         SASSERT(is_datatype(ty)); | ||||
|         bool r = false; | ||||
|         if (!m_is_recursive.find(ty, r)) { | ||||
|         if (!plugin().m_is_recursive.find(ty, r)) { | ||||
|             r = is_recursive_core(ty); | ||||
|             m_is_recursive.insert(ty, r); | ||||
|             m_asts.push_back(ty); | ||||
|             plugin().m_is_recursive.insert(ty, r); | ||||
|             plugin().add_ast(ty); | ||||
|         } | ||||
|         return r; | ||||
|     } | ||||
|  | @ -1147,21 +1162,21 @@ namespace datatype { | |||
|         if (!is_datatype(s))  | ||||
|             return false;         | ||||
|         bool r = false; | ||||
|         if (m_is_enum.find(s, r)) | ||||
|         if (plugin().m_is_enum.find(s, r)) | ||||
|             return r; | ||||
|         ptr_vector<func_decl> const& cnstrs = *get_datatype_constructors(s); | ||||
|         r = true; | ||||
|         for (unsigned i = 0; r && i < cnstrs.size(); ++i)  | ||||
|             r = cnstrs[i]->get_arity() == 0;         | ||||
|         m_is_enum.insert(s, r); | ||||
|         m_asts.push_back(s); | ||||
|         plugin().m_is_enum.insert(s, r); | ||||
|         plugin().add_ast(s); | ||||
|         return r; | ||||
|     } | ||||
| 
 | ||||
|     func_decl * util::get_accessor_constructor(func_decl * accessor) {  | ||||
|         SASSERT(is_accessor(accessor)); | ||||
|         func_decl * r = nullptr; | ||||
|         if (m_accessor2constructor.find(accessor, r)) | ||||
|         if (plugin().m_accessor2constructor.find(accessor, r)) | ||||
|             return r; | ||||
|         sort * datatype = accessor->get_domain(0); | ||||
|         symbol c_id   = accessor->get_parameter(1).get_symbol(); | ||||
|  | @ -1174,26 +1189,15 @@ namespace datatype { | |||
|             } | ||||
|         } | ||||
|         r = fn; | ||||
|         m_accessor2constructor.insert(accessor, r); | ||||
|         m_asts.push_back(accessor); | ||||
|         m_asts.push_back(r); | ||||
|         plugin().m_accessor2constructor.insert(accessor, r); | ||||
|         plugin().add_ast(accessor); | ||||
|         plugin().add_ast(r); | ||||
|         return r; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void util::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(); | ||||
|         m_asts.reset(); | ||||
|         ++m_start; | ||||
|         plugin().reset(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1205,7 +1209,7 @@ namespace datatype { | |||
|     func_decl * util::get_non_rec_constructor(sort * ty) { | ||||
|         SASSERT(is_datatype(ty)); | ||||
|         cnstr_depth cd; | ||||
|         if (m_datatype2nonrec_constructor.find(ty, cd)) | ||||
|         if (plugin().m_datatype2nonrec_constructor.find(ty, cd)) | ||||
|             return cd.first; | ||||
|         ptr_vector<sort> forbidden_set; | ||||
|         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, | ||||
|        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
 | ||||
|         //   1) T_i's are not recursive
 | ||||
|         // 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); | ||||
|         array_util autil(m); | ||||
|         cnstr_depth result(nullptr, 0); | ||||
|         if (m_datatype2nonrec_constructor.find(ty, result)) | ||||
|         if (plugin().m_datatype2nonrec_constructor.find(ty, result)) | ||||
|             return result; | ||||
|         TRACE("util_bug", tout << "get-non-rec constructor: " << sort_ref(ty, m) << "\n"; | ||||
|               tout << "forbidden: "; | ||||
|  | @ -1273,9 +1277,9 @@ namespace datatype { | |||
|             } | ||||
|         } | ||||
|         if (result.first) { | ||||
|             m_asts.push_back(result.first); | ||||
|             m_asts.push_back(ty); | ||||
|             m_datatype2nonrec_constructor.insert(ty, result); | ||||
|             plugin().add_ast(result.first); | ||||
|             plugin().add_ast(ty); | ||||
|             plugin().m_datatype2nonrec_constructor.insert(ty, result); | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|  | @ -1291,6 +1295,7 @@ namespace datatype { | |||
|         IF_VERBOSE(0, verbose_stream() << f->get_name() << "\n"); | ||||
|         for (constructor* c : d) | ||||
|             IF_VERBOSE(0, verbose_stream() << "!= " << c->name() << "\n"); | ||||
|         return UINT_MAX; | ||||
|         SASSERT(false); | ||||
|         UNREACHABLE(); | ||||
|         return 0; | ||||
|  |  | |||
|  | @ -198,6 +198,8 @@ namespace datatype { | |||
|         def* translate(ast_translation& tr, util& u); | ||||
|     }; | ||||
| 
 | ||||
|     typedef std::pair<func_decl*, unsigned> cnstr_depth; | ||||
| 
 | ||||
|     namespace decl { | ||||
| 
 | ||||
|         class plugin : public decl_plugin { | ||||
|  | @ -213,6 +215,7 @@ namespace datatype { | |||
| 
 | ||||
|             void log_axiom_definitions(symbol const& s, sort * new_sort); | ||||
| 
 | ||||
| 
 | ||||
|         public: | ||||
|             plugin(): m_id_counter(0), m_class_id(0), m_has_nested_rec(false) {} | ||||
|             ~plugin() override; | ||||
|  | @ -259,6 +262,25 @@ namespace datatype { | |||
| 
 | ||||
|             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: | ||||
|             bool is_value_visit(bool unique, expr * arg, ptr_buffer<app> & todo) const; | ||||
|             bool is_value_aux(bool unique, app * arg) const; | ||||
|  | @ -295,25 +317,10 @@ namespace datatype { | |||
|         ast_manager & m; | ||||
|         mutable family_id     m_family_id; | ||||
|         mutable decl::plugin* m_plugin; | ||||
|         typedef std::pair<func_decl*, unsigned> cnstr_depth; | ||||
| 
 | ||||
| 
 | ||||
|         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); | ||||
| 
 | ||||
|         friend class decl::plugin; | ||||
|  |  | |||
|  | @ -97,42 +97,41 @@ public: | |||
| }; | ||||
| 
 | ||||
| struct statistics { | ||||
|     unsigned m_make_feasible; | ||||
|     unsigned m_total_iterations; | ||||
|     unsigned m_iters_with_no_cost_growing; | ||||
|     unsigned m_num_factorizations; | ||||
|     unsigned m_num_of_implied_bounds; | ||||
|     unsigned m_need_to_solve_inf; | ||||
|     unsigned m_max_cols; | ||||
|     unsigned m_max_rows; | ||||
|     unsigned m_gcd_calls; | ||||
|     unsigned m_gcd_conflicts; | ||||
|     unsigned m_cube_calls; | ||||
|     unsigned m_cube_success; | ||||
|     unsigned m_patches; | ||||
|     unsigned m_patches_success; | ||||
|     unsigned m_hnf_cutter_calls; | ||||
|     unsigned m_hnf_cuts; | ||||
|     unsigned m_nla_calls; | ||||
|     unsigned m_gomory_cuts; | ||||
|     unsigned m_nla_add_bounds; | ||||
|     unsigned m_nla_propagate_bounds; | ||||
|     unsigned m_nla_propagate_eq; | ||||
|     unsigned m_nla_lemmas; | ||||
|     unsigned m_nra_calls; | ||||
|     unsigned m_nla_bounds_improvements; | ||||
|     unsigned m_horner_calls; | ||||
|     unsigned m_horner_conflicts; | ||||
|     unsigned m_cross_nested_forms; | ||||
|     unsigned m_grobner_calls; | ||||
|     unsigned m_grobner_conflicts; | ||||
|     unsigned m_offset_eqs; | ||||
|     unsigned m_fixed_eqs; | ||||
|     ::statistics m_st; | ||||
|     statistics() { reset(); } | ||||
|     unsigned m_make_feasible = 0; | ||||
|     unsigned m_total_iterations = 0; | ||||
|     unsigned m_iters_with_no_cost_growing = 0; | ||||
|     unsigned m_num_factorizations = 0; | ||||
|     unsigned m_num_of_implied_bounds = 0; | ||||
|     unsigned m_need_to_solve_inf = 0; | ||||
|     unsigned m_max_cols = 0; | ||||
|     unsigned m_max_rows = 0; | ||||
|     unsigned m_gcd_calls = 0; | ||||
|     unsigned m_gcd_conflicts = 0; | ||||
|     unsigned m_cube_calls = 0; | ||||
|     unsigned m_cube_success = 0; | ||||
|     unsigned m_patches = 0; | ||||
|     unsigned m_patches_success = 0; | ||||
|     unsigned m_hnf_cutter_calls = 0; | ||||
|     unsigned m_hnf_cuts = 0; | ||||
|     unsigned m_nla_calls = 0; | ||||
|     unsigned m_gomory_cuts = 0; | ||||
|     unsigned m_nla_add_bounds = 0; | ||||
|     unsigned m_nla_propagate_bounds = 0; | ||||
|     unsigned m_nla_propagate_eq = 0; | ||||
|     unsigned m_nla_lemmas = 0; | ||||
|     unsigned m_nra_calls = 0; | ||||
|     unsigned m_nla_bounds_improvements = 0; | ||||
|     unsigned m_horner_calls = 0; | ||||
|     unsigned m_horner_conflicts = 0; | ||||
|     unsigned m_cross_nested_forms = 0; | ||||
|     unsigned m_grobner_calls = 0; | ||||
|     unsigned m_grobner_conflicts = 0; | ||||
|     unsigned m_offset_eqs = 0; | ||||
|     unsigned m_fixed_eqs = 0; | ||||
|     ::statistics m_st = {}; | ||||
| 
 | ||||
|     void reset() { | ||||
|         memset(this, 0, sizeof(*this)); | ||||
|         m_st.reset(); | ||||
|         *this = statistics{}; | ||||
|     } | ||||
|     void collect_statistics(::statistics& st) const { | ||||
|         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 & 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); } | ||||
|     }; | ||||
|  |  | |||
|  | @ -92,7 +92,7 @@ static_matrix<T, X>::static_matrix(static_matrix const &A, unsigned * /* basis * | |||
|     init_row_columns(m, m); | ||||
|     for (; m-- > 0; )  | ||||
|         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() { | ||||
|  |  | |||
|  | @ -141,6 +141,8 @@ namespace nlsat { | |||
|                 auto& a = *to_ineq_atom(a1); | ||||
|                 if (a.size() != 2) | ||||
|                     continue; | ||||
|                 if (a.is_root_atom()) | ||||
|                     continue; | ||||
| 
 | ||||
|                 auto* p = a.p(0); | ||||
|                 auto* q = a.p(1); | ||||
|  | @ -229,6 +231,10 @@ namespace nlsat { | |||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|                 default: | ||||
|                     SASSERT(a.is_root_atom()); | ||||
|                     UNREACHABLE(); | ||||
|                     break; | ||||
|                 } | ||||
|                 IF_VERBOSE(3,  | ||||
|                 s.display(verbose_stream(), c) << " ->\n"; | ||||
|  |  | |||
|  | @ -101,7 +101,7 @@ struct mbp_basic_tg::impl { | |||
|                 bool is_or = m.is_or(term); | ||||
|                 app *c = to_app(term); | ||||
|                 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) { | ||||
|                     mark_seen(term); | ||||
|                     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 <iostream> | ||||
| #include "util/dlist.h" | ||||
|  | @ -160,10 +177,12 @@ void tst_dlist() { | |||
|     test_pop(); | ||||
|     test_insert_after(); | ||||
|     test_insert_before(); | ||||
| #if 0 | ||||
|     test_remove_from(); | ||||
|     test_push_to_front(); | ||||
|     test_detach(); | ||||
|     test_invariant(); | ||||
|     test_contains(); | ||||
| #endif | ||||
|     std::cout << "All tests passed." << std::endl; | ||||
| } | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ Abstract: | |||
| Author: | ||||
| 
 | ||||
|     Leonardo de Moura (leonardo) 2006-09-12. | ||||
|     Chuyue Sun (liviasun) 2024-07-18. | ||||
| 
 | ||||
| Revision History: | ||||
| 
 | ||||
|  | @ -20,7 +21,6 @@ Revision History: | |||
| #include<iostream> | ||||
| #include<unordered_set> | ||||
| #include<stdlib.h> | ||||
| 
 | ||||
| #include "util/hashtable.h" | ||||
| 
 | ||||
| 
 | ||||
|  | @ -119,11 +119,126 @@ static void tst3() { | |||
|     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() { | ||||
|     tst3(); | ||||
|     for (int i = 0; i < 100; i++)  | ||||
|         tst2(); | ||||
|     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 | ||||
| void tst_hashtable() { | ||||
|  |  | |||
|  | @ -157,20 +157,12 @@ public: | |||
| 
 | ||||
|     bool invariant() const { | ||||
|         auto* e = this; | ||||
|         const T* slow = static_cast<const T*>(this);  | ||||
|         const T* fast = m_next;  | ||||
|         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. 
 | ||||
|         do { | ||||
|             if (e->m_next->m_prev != e) | ||||
|                 return false; | ||||
|             e = e->m_next; | ||||
|         } | ||||
|         while (e != this); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ Abstract: | |||
| Author: | ||||
| 
 | ||||
|     Leonardo de Moura (leonardo) 2006-09-11. | ||||
|     Chuyue Sun (liviasun) 2024-07-18. | ||||
| 
 | ||||
| Revision History: | ||||
| 
 | ||||
|  | @ -639,6 +640,19 @@ public: | |||
| 
 | ||||
| #ifdef Z3DEBUG | ||||
|     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 * end  = m_table + m_capacity; | ||||
|         unsigned num_deleted = 0; | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ void permutation::swap(unsigned i, unsigned j) noexcept { | |||
|     unsigned j_prime = m_p[j]; | ||||
|     std::swap(m_p[i], m_p[j]); | ||||
|     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 { | ||||
|     SASSERT(m_p.size() == m_inv_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++) { | ||||
|         unsigned pi = m_p[i]; | ||||
|         SASSERT(m_p[i] < n); | ||||
|         SASSERT(m_inv_p[i] < n); | ||||
|         SASSERT(m_p[m_inv_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; | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue