/*++ Copyright (c) 2015 Microsoft Corporation Module Name: symbolic_automata.h Abstract: Symbolic Automata over Boolean Algebras, a la Margus Veanes Automata library. Author: Nikolaj Bjorner (nbjorner) 2016-02-27. Revision History: --*/ #pragma once #include "math/automata/automaton.h" #include "math/automata/boolean_algebra.h" template > class symbolic_automata { typedef automaton automaton_t; typedef boolean_algebra ba_t; typedef typename automaton_t::move move_t; typedef vector moves_t; typedef obj_ref ref_t; typedef ref_vector refs_t; typedef std::pair unsigned_pair; template class u2_map : public map, default_eq > {}; M& m; ba_t& m_ba; class block { uint_set m_set; unsigned m_rep; bool m_rep_chosen; public: block(): m_rep(0), m_rep_chosen(false) {} block(uint_set const& s): m_set(s), m_rep(0), m_rep_chosen(false) { } block(unsigned_vector const& vs) { for (unsigned i = 0; i < vs.size(); ++i) { m_set.insert(vs[i]); } m_rep_chosen = false; m_rep = 0; } block& operator=(block const& b) { m_set = b.m_set; m_rep = 0; m_rep_chosen = false; return *this; } unsigned get_representative() { if (!m_rep_chosen) { uint_set::iterator it = m_set.begin(); if (m_set.end() != it) { m_rep = *it; } m_rep_chosen = true; } return m_rep; } void insert(unsigned i) { m_set.insert(i); } bool contains(unsigned i) const { return m_set.contains(i); } bool is_empty() const { return m_set.empty(); } unsigned size() const { return m_set.num_elems(); } void remove(unsigned i) { m_set.remove(i); m_rep_chosen = false; } void clear() { m_set.reset(); m_rep_chosen = false; } uint_set::iterator begin() const { return m_set.begin(); } uint_set::iterator end() const { return m_set.end(); } }; void add_block(block const& p1, unsigned p0_index, unsigned_vector& blocks, vector& pblocks, unsigned_vector& W); public: symbolic_automata(M& m, ba_t& ba): m(m), m_ba(ba) {} automaton_t* mk_determinstic(automaton_t& a); automaton_t* mk_complement(automaton_t& a); automaton_t* remove_epsilons(automaton_t& a); automaton_t* mk_total(automaton_t& a); automaton_t* mk_minimize(automaton_t& a); automaton_t* mk_minimize_total(automaton_t& a); automaton_t* mk_difference(automaton_t& a, automaton_t& b); automaton_t* mk_product(automaton_t& a, automaton_t& b); private: automaton_t* mk_determinstic_param(automaton_t& a, bool flip_acceptance); vector, ref_t> > generate_min_terms(vector &constraints) { vector, ref_t> > min_terms; ref_t curr_pred(m_ba.mk_true(), m); vector curr_bv; generate_min_terms_rec(constraints, min_terms, 0, curr_bv, curr_pred); return min_terms; } void generate_min_terms_rec(vector &constraints, vector, ref_t> > &min_terms, unsigned i, vector &curr_bv, ref_t &curr_pred) { lbool is_sat = m_ba.is_sat(curr_pred); if (is_sat == l_undef) throw default_exception("incomplete theory: unable to generate min-terms"); if (is_sat != l_true) { return; } if (i == constraints.size()) { min_terms.push_back(std::pair, ref_t>(curr_bv, curr_pred)); } else { //true case curr_bv.push_back(true); ref_t new_pred_pos(m_ba.mk_and(curr_pred, constraints[i]), m); generate_min_terms_rec(constraints, min_terms, i + 1, curr_bv, new_pred_pos); curr_bv.pop_back(); //false case curr_bv.push_back(false); ref_t neg(m_ba.mk_not(constraints[i]), m); ref_t new_pred_neg(m_ba.mk_and(curr_pred, neg), m); generate_min_terms_rec(constraints, min_terms, i + 1, curr_bv, new_pred_neg); curr_bv.pop_back(); } } };