/* * Copyright (C) 1999, 2000, 2001, 2002 * Heikki Tauriainen * * This program 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 2 * of the License, or (at your option) any later version. * * This program 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef BUCHIAUTOMATON_H #define BUCHIAUTOMATON_H #ifdef __GNUC__ #pragma interface #endif /* __GNUC__ */ #include #include #include #include #include "Alloc.h" #include "BitArray.h" #include "EdgeContainer.h" #include "Exception.h" #include "Graph.h" #include "LtlFormula.h" using namespace std; namespace Graph { /****************************************************************************** * * A class for representing Büchi automata with a single set of accepting * states. * *****************************************************************************/ class BuchiAutomaton : public Graph { public: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ class BuchiTransition; /* A class for representing * the transitions between * the states of the * automaton. */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ class BuchiState : /* A class for */ public Graph::Node /* representing the */ { /* states of the * automaton. */ public: explicit BuchiState /* Constructor. */ (const unsigned long int num_of_acceptance_sets); ~BuchiState(); /* Destructor. */ /* `edges' inherited from Graph::Node */ BitArray& acceptanceSets(); /* Tell the acceptance */ const BitArray& acceptanceSets() const; /* status of the state. */ void print /* Writes information */ (ostream& stream, /* about the state to a */ const int indent, /* stream. */ const GraphOutputFormat fmt) const; void print /* Writes information */ (ostream& stream, /* about the state to a */ const int indent, /* stream. */ const GraphOutputFormat fmt, const unsigned long int number_of_acceptance_sets) const; private: BuchiState(const BuchiState&); /* Prevent copying and */ BuchiState& operator=(const BuchiState&); /* assignment of * BuchiState objects. */ BitArray acceptance_sets; /* Acceptance status of the * state. */ }; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ explicit BuchiAutomaton /* Constructor. */ (const size_type initial_number_of_states = 0, const size_type initstate = 0, const unsigned long int number_of_accept_sets = 0); BuchiAutomaton(const BuchiAutomaton& automaton); /* Copy constructor. */ ~BuchiAutomaton(); /* Destructor. */ BuchiAutomaton& /* Assignment operator. */ operator=(const BuchiAutomaton& automaton); BuchiState& operator[] /* Indexing operator. No */ (const size_type index) const; /* range check is * performed on the * argument. */ BuchiState& node(const size_type index) const; /* Synonym for the indexing * operator. This function * also checks the range of * the argument. */ /* `size' inherited from Graph */ /* `empty' inherited from Graph */ void clear(); /* Makes the automaton * empty. */ size_type expand(size_type node_count = 1); /* Inserts states to the * automaton. */ void connect /* Connects two states */ (const size_type father, /* of the automaton with */ const size_type child); /* an unguarded * transition. */ void connect /* Connects two states */ (const size_type father, const size_type child, /* of the automaton with */ ::Ltl::LtlFormula& guard); /* a transition guarded */ void connect /* by a propositional */ (const size_type father, const size_type child, /* formula. */ ::Ltl::LtlFormula* guard); /* `disconnect' inherited from Graph */ /* `connected' inherited from Graph */ /* `stats' inherited from Graph */ /* `subgraphStats' inherited from Graph */ size_type initialState() const; /* Get or set the */ size_type& initialState(); /* initial state of the * * automaton. */ unsigned long int numberOfAcceptanceSets() const; /* Returns the number of * acceptance sets in the * automaton. */ BuchiAutomaton* regularize() const; /* Converts a generalized * automaton to an * automaton with one set * of accepting states. */ void read(istream& input_stream); /* Reads the automaton * from a stream. */ void print /* Writes information */ (ostream& stream = cout, /* about the automaton */ const int indent = 0, /* to a stream in */ const GraphOutputFormat fmt = NORMAL) const; /* various formats * (determined by the * `fmt' argument). */ static BuchiAutomaton* intersect /* Computes the */ (const BuchiAutomaton& a1, /* intersection of two */ const BuchiAutomaton& a2, /* Büchi automata. */ map, ALLOC(StateIdPair) >* intersection_state_mapping = 0); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ class AutomatonParseException; /* Class for reporting * parse errors when * reading an automaton * description from a * stream. */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ private: size_type initial_state; /* Identifier of the * initial state of the * automaton. */ unsigned long int number_of_acceptance_sets; /* Number of acceptance * sets in the automaton. */ }; /****************************************************************************** * * A class for representing the transitions of a Büchi automaton. * *****************************************************************************/ class BuchiAutomaton::BuchiTransition : public Graph::Edge { public: BuchiTransition /* Constructor. */ (const size_type target, ::Ltl::LtlFormula* formula); ~BuchiTransition(); /* Destructor. */ private: public: /* `targetNode' inherited from Graph::Edge */ bool enabled /* These functions test */ (const BitArray& truth_assignment, /* whether the */ const unsigned long int assignment_size) /* transition is */ const; /* enabled in a given */ /* truth assignment for */ bool enabled /* the atomic */ (const Bitset& truth_assignment) const; /* propositions. */ ::Ltl::LtlFormula& guard() const; /* Returns the * propositional formula * guarding the transition. */ void print /* Writes information */ (ostream& stream = cout, /* about the transition */ const int indent = 0, /* to a stream in */ const GraphOutputFormat fmt = NORMAL) const; /* various formats * (determined by the * `fmt' argument). */ private: BuchiTransition(const BuchiTransition&); /* Prevent copying and */ BuchiTransition& operator= /* assignment of */ (const BuchiTransition&); /* BuchiTransition * objects. */ bool operator== /* Equality test. Used */ (const Graph::Edge& /* for sorting */ transition) const; /* transitions in an STL * container. */ bool operator< /* `Less than' relation. */ (const Graph::Edge& /* Used for sorting */ transition) const; /* transitions in an STL * container. */ ::Ltl::LtlFormula* guard_formula; /* The propositional * formula guarding the * transition. */ }; /****************************************************************************** * * A class for reporting parse errors when reading an automaton description * from a stream. * *****************************************************************************/ class BuchiAutomaton::AutomatonParseException : public Exception { public: AutomatonParseException /* Constructor. */ (const string& msg = "parse error"); /* default copy constructor */ ~AutomatonParseException() throw(); /* Destructor. */ AutomatonParseException& /* Assignment operator. */ operator=(const AutomatonParseException& e); /* `what' inherited from class Exception */ }; /****************************************************************************** * * Inline function definitions for class BuchiAutomaton. * *****************************************************************************/ /* ========================================================================= */ inline BuchiAutomaton::~BuchiAutomaton() /* ---------------------------------------------------------------------------- * * Description: Destructor for class BuchiAutomaton. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline BuchiAutomaton::BuchiState& BuchiAutomaton::operator[] (const size_type index) const /* ---------------------------------------------------------------------------- * * Description: Indexing operator for class BuchiAutomaton. This function can * be used to refer to the individual states of the automaton. * No range check will be performed on the argument. * * Argument: index -- Index of a state. * * Returns: A reference to a state of the automaton. * * ------------------------------------------------------------------------- */ { return static_cast(*nodes[index]); } /* ========================================================================= */ inline BuchiAutomaton::BuchiState& BuchiAutomaton::node (const size_type index) const /* ---------------------------------------------------------------------------- * * Description: Function for referring to a single state of a BuchiAutomaton. * This function will perform a range check on the argument. * * Argument: index -- Index of a state. * * Returns: A reference to a state of the automaton. * * ------------------------------------------------------------------------- */ { return static_cast(Graph::node(index)); } /* ========================================================================= */ inline void BuchiAutomaton::connect (const size_type father, const size_type child) /* ---------------------------------------------------------------------------- * * Description: Connects two states of a BuchiAutomaton to each other with an * unguarded transition (actually, a transition with a guard * that is always true). * * Arguments: father -- Source state identifier. * child -- Target state identifier. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { connect(father, child, &(::Ltl::True::construct())); } /* ========================================================================= */ inline void BuchiAutomaton::connect (const size_type father, const size_type child, ::Ltl::LtlFormula& guard) /* ---------------------------------------------------------------------------- * * Description: Connects two states of a BuchiAutomaton to each other, using * a LtlFormula (which is actually a propositional formula) to * guard the transition between the states. * * Arguments: father -- Source state. * child -- Target state. * guard -- A reference to an LtlFormula (a propositional * formula) guarding the transition. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { connect(father, child, guard.clone()); } /* ========================================================================= */ inline void BuchiAutomaton::connect (const size_type father, const size_type child, ::Ltl::LtlFormula* guard) /* ---------------------------------------------------------------------------- * * Description: Connects two states of a BuchiAutomaton to each other, using * a LtlFormula (which is actually a propositional formula) to * guard the transition between the states. * * Arguments: father -- Source state. * child -- Target state. * guard -- A pointer to an LtlFormula (a propositional * formula) guarding the transition. The transition * will "own" the guard formula. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { BuchiTransition* new_buchi_transition = new BuchiTransition(child, guard); try { nodes[father]->outgoing_edges.insert(new_buchi_transition); } catch (...) { delete new_buchi_transition; throw; } } /* ========================================================================= */ inline BuchiAutomaton::size_type BuchiAutomaton::initialState() const /* ---------------------------------------------------------------------------- * * Description: Returns the initial state of the BuchiAutomaton by value. * * Arguments: None. * * Returns: Index of the initial state of the automaton. * * ------------------------------------------------------------------------- */ { return initial_state; } /* ========================================================================= */ inline BuchiAutomaton::size_type& BuchiAutomaton::initialState() /* ---------------------------------------------------------------------------- * * Description: Returns the initial state of the BuchiAutomaton by reference. * This function can therefore be used to change the initial * state. * * Arguments: None. * * Returns: A reference to the value of the initial state. * * ------------------------------------------------------------------------- */ { return initial_state; } /* ========================================================================= */ inline unsigned long int BuchiAutomaton::numberOfAcceptanceSets() const /* ---------------------------------------------------------------------------- * * Description: Returns the number of acceptance sets in the automaton. * * Arguments: None. * * Returns: The number of acceptance sets in the automaton. * * ------------------------------------------------------------------------- */ { return number_of_acceptance_sets; } /* ========================================================================= */ inline istream& operator>>(istream& stream, BuchiAutomaton& automaton) /* ---------------------------------------------------------------------------- * * Description: Defines an alternative method for reading an automaton from * a stream by using the >> operator. * * Arguments: stream -- A reference to an input stream. * automaton -- A reference to the BuchiAutomaton. * * Returns: A reference to the input stream. * * ------------------------------------------------------------------------- */ { automaton.read(stream); return stream; } /****************************************************************************** * * Inline function definitions for class BuchiAutomaton::BuchiTransition. * *****************************************************************************/ /* ========================================================================= */ inline BuchiAutomaton::BuchiTransition::BuchiTransition (const size_type target, ::Ltl::LtlFormula* formula) : Edge(target), guard_formula(formula) /* ---------------------------------------------------------------------------- * * Description: Constructor for class BuchiAutomaton::BuchiTransition. * Initializes a new transition to a BuchiState, guarded by an * LtlFormula (which is actually a propositional formula). * * Arguments: target -- Identifier of the target state of the automaton. * formula -- A pointer to a propositional formula guarding * the transition. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline BuchiAutomaton::BuchiTransition::BuchiTransition (const BuchiTransition& transition) : Edge(transition), guard_formula(transition.guard_formula->clone()) /* ---------------------------------------------------------------------------- * * Description: Copy constructor for class BuchiAutomaton::BuchiTransition. * Creates a copy of a BuchiTransition object. * * Arguments: transition -- BuchiTransition to be copied. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline BuchiAutomaton::BuchiTransition::~BuchiTransition() /* ---------------------------------------------------------------------------- * * Description: Destructor for class BuchiAutomaton::BuchiTransition. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { ::Ltl::LtlFormula::destruct(guard_formula); } /* ========================================================================= */ inline bool BuchiAutomaton::BuchiTransition::operator== (const Graph::Edge& transition) const /* ---------------------------------------------------------------------------- * * Description: Equality relation for comparing two BuchiTransitions. Two * transitions are `equal' if and only if their target nodes * have the same identifier and if their guard formulae are * identical according to the `less' * relation. * * Argument: transition -- A reference to a constant Edge. * * Returns: Truth value according to the relationship between the two * transitions. * * ------------------------------------------------------------------------- */ { /* * This function is called only when comparing two edges stored in the * `outgoing_edges' GraphEdgeContainer of some state in a BuchiAutomaton. * Since (pointers to) BuchiTransitions are never mixed with other types in * that container, it is always safe to static_cast `transition' to a * reference to a BuchiTransition. */ return (Edge::operator==(transition) && !(guard_formula < static_cast(transition) .guard_formula) && !(static_cast(transition).guard_formula < guard_formula)); } /* ========================================================================= */ inline bool BuchiAutomaton::BuchiTransition::operator< (const Graph::Edge& transition) const /* ---------------------------------------------------------------------------- * * Description: `Less than' relation for comparing two BuchiTransitions. A * BuchiTransition is `less than' another if and only if the * identifier of its target node is less than that of the other * or the target nodes agree but the guard formula of the * first transition is `less than' the other according to the * `less' relation. * * Argument: transition -- A reference to a constant Edge. * * Returns: Truth value according to the relationship between the two * transitions. * * ------------------------------------------------------------------------- */ { /* * This function is called only when comparing two edges stored in the * `outgoing_edges' GraphEdgeContainer of some state in a BuchiAutomaton. * Since (pointers to) BuchiTransitions are never mixed with other types in * that container, it is always safe to static_cast `transition' to a * reference to a BuchiTransition. */ return (Edge::operator<(transition) || (Edge::operator==(transition) && guard_formula < static_cast(transition) .guard_formula)); } /* ========================================================================= */ inline bool BuchiAutomaton::BuchiTransition::enabled (const BitArray& truth_assignment, const unsigned long int assignment_size) const /* ---------------------------------------------------------------------------- * * Description: Determines whether the transition is enabled in a given * truth assignment for propositional variables. * * Arguments: truth_assignment -- A reference to a constant BitArray * representing an assignment of truth * values to propositional variables. * assignment_size -- Number of propositions in the * truth assignment. * * Returns: A truth value telling whether the transition is enabled in * the truth assignment. * * ------------------------------------------------------------------------- */ { return guard_formula->evaluate(truth_assignment, assignment_size); } /* ========================================================================= */ inline bool BuchiAutomaton::BuchiTransition::enabled (const Bitset& truth_assignment) const /* ---------------------------------------------------------------------------- * * Description: See above. * * Arguments: truth_assignment -- A reference to a constant Bitset * representing an assignment of truth * values to propositional variables. * * Returns: A truth value telling whether the transition is enabled in * the truth assignment. * * ------------------------------------------------------------------------- */ { return enabled(truth_assignment, truth_assignment.capacity()); } /* ========================================================================= */ inline ::Ltl::LtlFormula& BuchiAutomaton::BuchiTransition::guard() const /* ---------------------------------------------------------------------------- * * Description: Returns the propositional formula guarding the transition * (a LtlFormula object). * * Arguments: None. * * Returns: A reference to the constant propositional formula guarding * the transition. * * ------------------------------------------------------------------------- */ { return *guard_formula; } /****************************************************************************** * * Inline function definitions for class BuchiAutomaton::BuchiState. * *****************************************************************************/ /* ========================================================================= */ inline BuchiAutomaton::BuchiState::BuchiState (const unsigned long int num_of_acceptance_sets) : Node(), acceptance_sets(num_of_acceptance_sets) /* ---------------------------------------------------------------------------- * * Description: Constructor for class BuchiAutomaton::BuchiState. Initializes * a new state for the automaton. * * Argument: num_of_acceptance_sets -- Number of acceptance sets in the * automaton to which the state * belongs. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { acceptance_sets.clear(num_of_acceptance_sets); } /* ========================================================================= */ inline BuchiAutomaton::BuchiState::~BuchiState() /* ---------------------------------------------------------------------------- * * Description: Destructor for class BuchiAutomaton::BuchiState. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline BitArray& BuchiAutomaton::BuchiState::acceptanceSets() /* ---------------------------------------------------------------------------- * * Description: Returns the acceptance status of the BuchiState, i.e. the * BitArray indicating the acceptance sets to which the state * belongs. * * Arguments: None. * * Returns: A reference to a BitArray object telling the acceptance sets * to which the state belongs. * * ------------------------------------------------------------------------- */ { return acceptance_sets; } /* ========================================================================= */ inline const BitArray& BuchiAutomaton::BuchiState::acceptanceSets() const /* ---------------------------------------------------------------------------- * * Description: Returns the acceptance status of the BuchiState, i.e. the * BitArray indicating the acceptance sets to which the state * belongs. * * Arguments: None. * * Returns: A reference to a constant BitArray object telling the * acceptance sets to which the state belongs. * * ------------------------------------------------------------------------- */ { return acceptance_sets; } /* ========================================================================= */ inline void BuchiAutomaton::BuchiState::print (ostream& stream, const int indent, const GraphOutputFormat fmt) const /* ---------------------------------------------------------------------------- * * Description: Writes information about a state of a Büchi automaton, * assuming that the (unspecified) maximum number of acceptance * sets in the automaton is 0. [Note: This function is used * to override the `print' function defined in the base class * `Graph::Node'.] * * Arguments: stream -- A reference to an output stream. * indent -- Number of spaces to leave to the left of output. * fmt -- Determines the output format of the state. * * Returns: Nothing. * * ------------------------------------------------------------------------ */ { this->print(stream, indent, fmt, 0); } /****************************************************************************** * * Inline function definitions for class * BuchiAutomaton::AutomatonParseException. * *****************************************************************************/ /* ========================================================================= */ inline BuchiAutomaton::AutomatonParseException::AutomatonParseException (const string& msg) : Exception(msg) /* ---------------------------------------------------------------------------- * * Description: Constructor for class * BuchiAutomaton::AutomatonParseException. Initializes a new * exception object with an error message. * * Argument: msg -- A reference to a constant string containing the * error message. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline BuchiAutomaton::AutomatonParseException::~AutomatonParseException() throw() /* ---------------------------------------------------------------------------- * * Description: Destructor for class BuchiAutomaton::AutomatonParseException. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline BuchiAutomaton::AutomatonParseException& BuchiAutomaton::AutomatonParseException::operator= (const AutomatonParseException& e) /* ---------------------------------------------------------------------------- * * Description: Assignment operator for class * BuchiAutomaton::AutomatonParseException. Assigns the contents * of another object of the same type to the exception object. * * Argument: e -- A reference to a constant exception object of the * same type. * * Returns: A reference to the exception object assigned to. * * ------------------------------------------------------------------------- */ { Exception::operator=(e); return *this; } } #endif /* !BUCHIAUTOMATON_H */