/*++ Copyright (c) 2006 Microsoft Corporation Module Name: func_interp.h Abstract: Support for function graphs (aka interpretations for functions). They are used during model construction, and for evaluating expressions modulo a model. Main goal: Remove some code duplication and make the evaluator more efficient. Example of code duplication that existed in Z3: - smt_model_generator was creating func_values that were essentially partial func_interps - smt_model_generator was creating if-then-else (lambda) exprs representing func_values - the model object was converting these lambdas back into func_graphs (a limited version of func_interps). - the smt_model_finder needs to manipulate func_interps, but the func_values in smt_model_generator were private and too restrictive. Author: Leonardo de Moura (leonardo) 2010-12-30. Revision History: --*/ #pragma once #include "ast/ast.h" #include "ast/ast_translation.h" class func_interp; class func_entry { bool m_args_are_values; //!< true if is_value(m_args[i]) is true for all i in [0, arity) // m_result and m_args[i] must be ground terms. expr * m_result; expr * m_args[]; static unsigned get_obj_size(unsigned arity) { return sizeof(func_entry) + arity * sizeof(expr*); } func_entry(ast_manager & m, unsigned arity, expr * const * args, expr * result); friend class func_interp; void set_result(ast_manager & m, expr * r); public: static func_entry * mk(ast_manager & m, unsigned arity, expr * const * args, expr * result); bool args_are_values() const { return m_args_are_values; } void deallocate(ast_manager & m, unsigned arity); expr * get_result() const { return m_result; } expr * get_arg(unsigned idx) const { return m_args[idx]; } expr * const * get_args() const { return m_args; } /** \brief Return true if m.are_equal(m_args[i], args[i]) for all i in [0, arity) */ bool eq_args(ast_manager & m, unsigned arity, expr * const * args) const; }; class func_interp { ast_manager & m_manager; unsigned m_arity; ptr_vector m_entries; expr * m_else; bool m_args_are_values; //!< true if forall e in m_entries e.args_are_values() == true expr * m_interp; //!< cache for representing the whole interpretation as a single expression (it uses ite terms). expr * m_array_interp; // ::const_iterator begin() const { return m_entries.begin(); } ptr_vector::const_iterator end() const { return m_entries.end(); } func_entry const * const * get_entries() const { return m_entries.data(); } func_entry const * get_entry(unsigned idx) const { return m_entries[idx]; } void del_entry(unsigned idx); expr * get_max_occ_result() const; void compress(); expr * get_interp() const; expr_ref get_array_interp(func_decl* f) const; func_interp * translate(ast_translation & translator) const; private: bool is_fi_entry_expr(expr * e, ptr_vector & args); bool is_identity() const; };