/*++ Copyright (c) 2013 Microsoft Corporation Module Name: pb_decl_plugin.h Abstract: Pseudo-Boolean and Cardinality Constraints plugin Author: Nikolaj Bjorner (nbjorner) 2013-05-11 Notes: (at-most-k x1 .... x_n) means x1 + ... + x_n <= k hence: (not (at-most-k x1 .... x_n)) means x1 + ... + x_n >= k + 1 --*/ #pragma once #include "ast/ast.h" enum pb_op_kind { OP_AT_MOST_K, // at most K Booleans are true. OP_AT_LEAST_K, // at least K Booleans are true. OP_PB_LE, // pseudo-Boolean <= (generalizes at_most_k) OP_PB_GE, // pseudo-Boolean >= OP_PB_EQ, // equality OP_PB_AUX_BOOL, // auxiliary internal Boolean variable. LAST_PB_OP }; class pb_decl_plugin : public decl_plugin { symbol m_at_most_sym; symbol m_at_least_sym; symbol m_pble_sym; symbol m_pbge_sym; symbol m_pbeq_sym; func_decl * mk_at_most(unsigned arity, unsigned k); func_decl * mk_at_least(unsigned arity, unsigned k); func_decl * mk_le(unsigned arity, rational const* coeffs, int k); func_decl * mk_ge(unsigned arity, rational const* coeffs, int k); func_decl * mk_eq(unsigned arity, rational const* coeffs, int k); public: pb_decl_plugin(); sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) override { UNREACHABLE(); return nullptr; } decl_plugin * mk_fresh() override { return alloc(pb_decl_plugin); } // // Contract for func_decl: // parameters[0] - integer (at most k elements) // all sorts are Booleans // parameters[1] .. parameters[arity] - coefficients func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) override; void get_op_names(svector & op_names, symbol const & logic) override; bool is_considered_uninterpreted(func_decl * f) override { return false; } }; class pb_util { ast_manager & m; family_id m_fid; vector m_coeffs; vector m_params; rational m_k; void normalize(unsigned num_args, rational const* coeffs, rational const& k); public: pb_util(ast_manager& m):m(m), m_fid(m.mk_family_id("pb")) {} ast_manager & get_manager() const { return m; } family_id get_family_id() const { return m_fid; } app * mk_at_most_k(unsigned num_args, expr * const * args, unsigned k); app * mk_at_least_k(unsigned num_args, expr * const * args, unsigned k); app * mk_at_most_k(expr_ref_vector const& args, unsigned k) { return mk_at_most_k(args.size(), args.data(), k); } app * mk_at_least_k(expr_ref_vector const& args, unsigned k) { return mk_at_least_k(args.size(), args.data(), k); } app * mk_le(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k); app * mk_ge(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k); app * mk_eq(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k); app * mk_lt(unsigned num_args, rational const * coeffs, expr * const * args, rational const& k); bool is_pb(expr* t) const { return is_app(t) && to_app(t)->get_family_id() == get_family_id(); } bool is_at_most_k(func_decl *a) const; bool is_at_most_k(expr *a) const { return is_app(a) && is_at_most_k(to_app(a)->get_decl()); } bool is_at_most_k(expr *a, rational& k) const; bool is_at_least_k(func_decl *a) const; bool is_at_least_k(expr *a) const { return is_app(a) && is_at_least_k(to_app(a)->get_decl()); } bool is_at_least_k(expr *a, rational& k) const; rational get_k(func_decl *a) const; rational get_k(expr *a) const { return get_k(to_app(a)->get_decl()); } bool is_le(func_decl *a) const; bool is_le(expr *a) const { return is_app(a) && is_le(to_app(a)->get_decl()); } bool is_le(expr* a, rational& k) const; bool is_ge(func_decl* a) const; bool is_ge(expr* a) const { return is_app(a) && is_ge(to_app(a)->get_decl()); } bool is_ge(expr* a, rational& k) const; bool is_aux_bool(func_decl* f) const { return is_decl_of(f, m_fid, OP_PB_AUX_BOOL); } bool is_aux_bool(expr* e) const { return is_app_of(e, m_fid, OP_PB_AUX_BOOL); } rational get_coeff(expr* a, unsigned index) const { return get_coeff(to_app(a)->get_decl(), index); } rational get_coeff(func_decl* a, unsigned index) const; bool has_unit_coefficients(func_decl* f) const; bool has_unit_coefficients(expr* f) const { return is_app(f) && has_unit_coefficients(to_app(f)->get_decl()); } bool is_eq(func_decl* f) const; bool is_eq(expr* e) const { return is_app(e) && is_eq(to_app(e)->get_decl()); } bool is_eq(expr* e, rational& k) const; app* mk_fresh_bool(); private: rational to_rational(parameter const& p) const; };