// -*- coding: utf-8 -*- // Copyright (C) 2016, 2018, 2019 Laboratoire de Recherche et Développement // de l'Epita (LRDE). // // This file is part of Spot, a model checking library. // // Spot is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // Spot is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public // License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #pragma once #include #include #include namespace spot { /// \brief Helper class combine outgoing edges in alternating /// automata /// /// The idea is that you can call the operator() on some state to get an /// BDD representation of its outgoing edges (labels and /// destinations, but not acceptance marks). The BDD representation /// of different states can combined using & or | to build a new /// representation of some outgoing edges that can be attached to /// some state with new_dests. The use of BDDs helps removing /// superfluous edges. /// /// Beware that new_dests() just *appends* the transitions to the /// supplied state, it does not remove existing ones. /// /// operator() can be called on states with universal branching /// (that's actually the point), and can be called on state number /// that designate groupes of destination states (in that case the /// conjunction of all those states are taken). class SPOT_API outedge_combiner { private: const twa_graph_ptr& aut_; std::map state_to_var; std::map var_to_state; bdd vars_; public: outedge_combiner(const twa_graph_ptr& aut); ~outedge_combiner(); bdd operator()(unsigned st); void new_dests(unsigned st, bdd out) const; }; /// @{ /// \brief Combine two states in a conjunction. /// /// This creates a new state whose outgoing transitions are the /// conjunctions of the compatible transitions of s1 and s2. /// /// Acceptance marks are dropped. /// /// The results is very likely to be alternating. /// @} template SPOT_API unsigned states_and(const twa_graph_ptr& aut, I begin, I end) { if (begin == end) throw std::runtime_error ("state_and() expects an non-empty list of states"); outedge_combiner combiner(aut); bdd combination = bddtrue; while (begin != end) combination &= combiner(*begin++); unsigned new_s = aut->new_state(); combiner.new_dests(new_s, combination); return new_s; } template SPOT_API unsigned states_and(const twa_graph_ptr& aut, const std::initializer_list& il) { return states_and(aut, il.begin(), il.end()); } /// @} /// \brief Remove universal edges from an automaton. /// /// This procedure is restricted to weak alternating automata as /// input, and produces TGBAs as output. (Generalized Büchi /// acceptance is only used in presence of size-1 rejecting-SCCs.) /// /// \param named_states name each state for easier debugging /// /// \param aborter Return nullptr if the built automaton would /// be larger than the size specified by the \a aborter. /// @} SPOT_API twa_graph_ptr remove_alternation(const const_twa_graph_ptr& aut, bool named_states = false, const output_aborter* aborter = nullptr); // Remove universal edges on the fly. class SPOT_API univ_remover_state: public state { protected: std::set states_; bool is_reset_; public: univ_remover_state(const std::set& states); univ_remover_state(const univ_remover_state& other) : states_(other.states_), is_reset_(other.is_reset_) { } int compare(const state* other) const override; size_t hash() const override; state* clone() const override; const std::set& states() const; bool is_reset() const; }; class SPOT_API twa_univ_remover: public twa { private: const_twa_graph_ptr aut_; std::vector state_to_var_; std::map var_to_state_; bdd all_states_; public: twa_univ_remover(const const_twa_graph_ptr& aut); void allocate_state_vars(); const state* get_init_state() const override; twa_succ_iterator* succ_iter(const state* s) const override; std::string format_state(const state* s) const override; }; typedef std::shared_ptr twa_univ_remover_ptr; /// \brief Remove universal edges on the fly from an automaton. /// /// This function uses the Myiano & Hayashi (TCS 1984) breakpoint /// algorithm to construct a non-deterministic Büchi automaton from an /// alternating Büchi automaton on the fly. /// /// \verbatim /// @Article{ miyano.84.tcs, /// title = "Alternating finite automata on ω-words", /// journal = "Theoretical Computer Science", /// volume = "32", /// number = "3", /// pages = "321 - 330", /// year = "1984", /// author = "Satoru Miyano and Takeshi Hayashi", /// } SPOT_API twa_univ_remover_ptr remove_univ_otf(const const_twa_graph_ptr& aut); }