/*++ Copyright (c) 2020 Microsoft Corporation Module Name: q_model_fixer.h Abstract: Model-based quantifier instantiation model-finder plugin Author: Nikolaj Bjorner (nbjorner) 2020-10-02 Notes: Derives from smt/smt_model_finder.cpp Contains exclusively functionality that adjusts a model to make it easier to satisfy relevant universally quantified literals. --*/ #pragma once #include "sat/smt/sat_th.h" #include "solver/solver.h" #include "model/model_macro_solver.h" #include "qe/mbp/mbp_plugin.h" namespace euf { class solver; } namespace q { class solver; typedef obj_hashtable func_decl_set; class projection_function { protected: ast_manager& m; public: projection_function(ast_manager& m) : m(m) {} virtual ~projection_function() = default; virtual expr* mk_lt(expr* a, expr* b) = 0; expr* mk_le(expr* a, expr* b) { return m.mk_not(mk_lt(b, a)); } virtual bool operator()(expr* a, expr* b) const = 0; }; /** * meta-data for a projection function for f at index idx (indexed-decl). * The meta-data contains the set of model values that the idx'th argument of f * has and a map from model values to terms and back. */ struct projection_meta_data { projection_meta_data(ast_manager& m) : values(m) {} expr_ref_vector values; obj_map v2t; obj_map t2v; }; struct indexed_decl { func_decl* f; unsigned idx; indexed_decl() : f(nullptr), idx(0) {} indexed_decl(func_decl* f, unsigned idx): f(f), idx(idx) {} struct hash { unsigned operator()(indexed_decl const& d) const { return d.idx + d.f->hash(); } }; struct eq { bool operator()(indexed_decl const& a, indexed_decl const& b) const { return a.idx == b.idx && a.f == b.f; } }; }; class model_fixer : public quantifier2macro_infos { euf::solver& ctx; solver& m_qs; ast_manager& m; obj_map m_q2info; func_decl_dependencies m_dependencies; obj_map m_projections; map m_projection_data; scoped_ptr_vector m_projection_pinned; void add_projection_functions(model& mdl, ptr_vector const& qs); void add_projection_functions(model& mdl, func_decl* f); expr_ref add_projection_function(model& mdl, func_decl* f, unsigned idx); void collect_partial_functions(ptr_vector const& qs, func_decl_set& fns); projection_function* get_projection(sort* srt); projection_meta_data* get_projection_data(func_decl* f, unsigned idx) const { projection_meta_data* r = nullptr; m_projection_data.find(indexed_decl(f, idx), r); return r; } public: model_fixer(euf::solver& ctx, solver& qs); /** * Update model in order to best satisfy quantifiers. * For the array property fragment, update the model * such that the range of functions behaves monotonically * based on regions over the inputs. */ void operator()(model& mdl); quantifier_macro_info* operator()(quantifier* q) override; /* * Create a constraint that restricts the possible values of t to a finite set of values. * Add value constraints to solver? */ expr_ref restrict_arg(app* t, unsigned i); /* * Create inequality constraints for the i'th argument of t based on the current model. */ void invert_arg(app* t, unsigned i, expr* value, expr_ref_vector& lits); /* * Replace term that contains uninterpreted function over free variables with a ground term. */ expr* invert_app(app* t, expr* value); }; }