/* * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 * 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 STATESPACEPRODUCT_H #define STATESPACEPRODUCT_H #include #include "BitArray.h" #include "BuchiAutomaton.h" #include "EdgeContainer.h" #include "Graph.h" #include "StateSpace.h" using namespace std; namespace Graph { /****************************************************************************** * * A class with operations for checking the product of a Büchi automaton and * a state space for emptiness. * *****************************************************************************/ class StateSpaceProduct { public: StateSpaceProduct /* Constructor. */ (const Graph& a, const Graph& s); /* default copy constructor */ ~StateSpaceProduct(); /* Destructor. */ /* default assignment operator */ bool empty() const; /* Tells whether the * product of a Büchi * automaton and a state * space is (trivially) * empty. */ unsigned long int numberOfAcceptanceSets() const; /* Tells the number of * acceptance sets in a * Büchi automaton in its * product with a state * space. */ const BuchiAutomaton::BuchiState& firstComponent /* Mappings between a */ (const Graph::size_type /* product state */ state_id) const; /* identifier and */ const StateSpace::State& secondComponent /* states of the Büchi */ (const Graph::size_type /* automaton and the */ state_id) const; /* state space forming * the product. */ void mergeAcceptanceInformation /* Merges the acceptance */ (const Graph::Node& state, /* sets associated with */ const Graph::Node&, /* a state in the Büchi */ BitArray& acceptance_sets) const; /* automaton into a * collection of sets. */ void mergeAcceptanceInformation /* Merges the acceptance */ (const Graph::Edge& /* sets associated with */ buchi_transition, /* a transition in the */ const Graph::Edge&, /* Büchi automaton into */ BitArray& acceptance_sets) const; /* a collection of sets. */ void validateEdgeIterators /* Ensures that a pair */ (const Graph::Node& /* of transition */ buchi_state, /* iterators points to a */ const Graph::Node& /* transition beginning */ system_state, /* from a given state in */ GraphEdgeContainer::const_iterator& /* the product of a */ buchi_transition, /* Büchi automaton and */ GraphEdgeContainer::const_iterator& /* a state space. */ system_transition) const; void incrementEdgeIterators /* Updates a pair of */ (const Graph::Node& /* transition iterators */ buchi_state, /* to make them point to */ const Graph::Node& /* the "next" transition */ system_state, /* starting from a given */ GraphEdgeContainer::const_iterator& /* state in the product */ buchi_transition, /* of a Büchi automaton */ GraphEdgeContainer::const_iterator& /* and a state space. */ system_transition) const; private: const BuchiAutomaton& buchi_automaton; /* Büchi automaton * associated with the * product. */ const StateSpace& statespace; /* State space associated * with the product. */ }; /****************************************************************************** * * Inline function definitions for class StateSpaceProduct. * *****************************************************************************/ /* ========================================================================= */ inline StateSpaceProduct::StateSpaceProduct (const Graph& a, const Graph& s) : buchi_automaton(static_cast(a)), statespace(static_cast(s)) /* ---------------------------------------------------------------------------- * * Description: Constructor for class StateSpaceProduct. Initializes a new * object with operations for checking the emptiness of the * product of a Büchi automaton and a state space. * * Arguments: a -- A constant reference to a Graph * object, assumed to be a BuchiAutomaton. * s -- A constant reference to a Graph * object, assumed to be a StateSpace. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline StateSpaceProduct::~StateSpaceProduct() /* ---------------------------------------------------------------------------- * * Description: Destructor for class StateSpaceProduct. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline bool StateSpaceProduct::empty() const /* ---------------------------------------------------------------------------- * * Description: Tells whether the product of `this->buchi_automaton' and * `this->statespace' is (trivially) empty. * * Arguments: None. * * Returns: true iff either the Büchi automaton or the state space has * no states. * * ------------------------------------------------------------------------- */ { return (buchi_automaton.empty() || statespace.empty()); } /* ========================================================================= */ inline unsigned long int StateSpaceProduct::numberOfAcceptanceSets() const /* ---------------------------------------------------------------------------- * * Description: Tells the number of acceptance sets in the Büchi automaton * associated with a StateSpaceProduct object. * * Arguments: None. * * Returns: The number of acceptance sets in the automaton. * * ------------------------------------------------------------------------- */ { return buchi_automaton.numberOfAcceptanceSets(); } /* ========================================================================= */ inline const BuchiAutomaton::BuchiState& StateSpaceProduct::firstComponent (const Graph::size_type state_id) const /* ---------------------------------------------------------------------------- * * Description: Function for accessing states in the Büchi automaton * associated with a StateSpaceProduct object. * * Argument: state_id -- Identifier of a state in the automaton. * * Returns: A constant reference to a state in the automaton. * * ------------------------------------------------------------------------- */ { return buchi_automaton[state_id]; } /* ========================================================================= */ inline const StateSpace::State& StateSpaceProduct::secondComponent (const Graph::size_type state_id) const /* ---------------------------------------------------------------------------- * * Description: Function for accessing states in the state space associated * with a StateSpaceProduct object. * * Argument: state_id -- Identifier of a state in the state space. * * Returns: A constant reference to a state in the state space. * * ------------------------------------------------------------------------- */ { return statespace[state_id]; } /* ========================================================================= */ inline void StateSpaceProduct::mergeAcceptanceInformation (const Graph::Node& state, const Graph::Node&, BitArray& acceptance_sets) const /* ---------------------------------------------------------------------------- * * Description: Merges the acceptance sets associated with a state of a Büchi * automaton into a collection of sets. * * Arguments: state -- A constant reference to a state in the * automaton. * acceptance_sets -- A reference to a BitArray for storing * the result. The BitArray should have * capacity for (at least) * `this->buchi_automaton * .numberOfAcceptanceSets()' bits. * (The second argument is needed to allow the class * StateSpaceProduct to be used for instantiating the Product * template; see file Product.h.) * * Returns: Nothing. After the operation, `acceptance_sets[i] == true' * holds if `state.acceptanceSets().test(i) == true' for all * 0 <= i < `this->buchi_automaton.numberOfAcceptanceSets()'. * * ------------------------------------------------------------------------- */ { acceptance_sets.bitwiseOr (static_cast(state).acceptanceSets(), numberOfAcceptanceSets()); } /* ========================================================================= */ inline void StateSpaceProduct::mergeAcceptanceInformation (const Graph::Edge& buchi_transition, const Graph::Edge&, BitArray& acceptance_sets) const /* ---------------------------------------------------------------------------- * * Description: Merges the acceptance sets associated with a transition of a * Büchi automaton into a collection of sets. * * Arguments: transition -- A constant reference to a transition in * the automaton. * acceptance_sets -- A reference to a BitArray for storing * the result. The BitArray should have * capacity for (at least) * `this->buchi_automaton * .numberOfAcceptanceSets()' bits. * (The second argument is needed to allow the class * StateSpaceProduct to be used for instantiating the Product * template; see file Product.h.) * * Returns: Nothing. After the operation, `acceptance_sets[i] == true' * holds if `transition.acceptanceSets().test(i) == true' for * all * 0 <= i < `this->buchi_automaton.numberOfAcceptanceSets()'. * * ------------------------------------------------------------------------- */ { acceptance_sets.bitwiseOr (static_cast(buchi_transition) .acceptanceSets(), numberOfAcceptanceSets()); } /* ========================================================================= */ inline void StateSpaceProduct::validateEdgeIterators (const Graph::Node& buchi_state, const Graph::Node& system_state, GraphEdgeContainer::const_iterator& buchi_transition, GraphEdgeContainer::const_iterator& system_transition) const /* ---------------------------------------------------------------------------- * * Description: Checks whether a pair of transition iterators corresponds to * a transition beginning from a state in the product of a Büchi * automaton and a state space; if this is not the case, makes * the iterators point to a valid transition beginning from the * product state (or to the "end" of the collection of * transitions beginning from the product state if no valid * transition can be found by incrementing the iterators). * * Arguments: buchi_state, -- These variables determine the state * system_state, in the product; `buchi_state' and * `system_state' should be references to * states in `this->buchi_automaton' and * `this->statespace', respectively. * buchi_transition, -- References to the transition * system_transition iterators. It is assumed that * `buchi_transition' and * `system_transition' initially point to * two transitions starting from * `buchi_state' and `system_state', * respectively. * * Returns: Nothing. Upon return, `buchi_transition' and * `system_transition' will either equal * `buchi_state.edges().end()' and `system_state.edges().end()', * respectively, or they will point to a pair of transitions * beginning from `buchi_state' and `system_state' such that * this pair of transitions corresponds to a transition starting * from the product state determined by `buchi_state' and * `system_state'. * * ------------------------------------------------------------------------- */ { const GraphEdgeContainer& buchi_transitions = buchi_state.edges(); const GraphEdgeContainer& system_transitions = system_state.edges(); if (buchi_transition == buchi_transitions.end()) { system_transition = system_transitions.end(); return; } if (system_transition == system_transitions.end()) { buchi_transition = buchi_transitions.end(); return; } while (!static_cast (*buchi_transition)->enabled (static_cast(system_state) .positiveAtoms(), statespace.numberOfPropositions())) { ++buchi_transition; if (buchi_transition == buchi_transitions.end()) { system_transition = system_transitions.end(); return; } } system_transition = system_transitions.begin(); } /* ========================================================================= */ inline void StateSpaceProduct::incrementEdgeIterators (const Graph::Node& buchi_state, const Graph::Node& system_state, GraphEdgeContainer::const_iterator& buchi_transition, GraphEdgeContainer::const_iterator& system_transition) const /* ---------------------------------------------------------------------------- * * Description: Increments a pair of transition iterators to point to the * "next" transition beginning from a state in the product of a * Büchi automaton and a state space. If no "next" transition * exists, makes the iterators point to the "end" of the * collection of transitions beginning from the product state. * * Arguments: buchi_state, -- These variables determine the state * system_state, in the product; `buchi_state' and * `system_state' should be references to * states in `this->buchi_automaton' and * `this->statespace', respectively. * buchi_transition, -- References to the transition * system_transition iterators. It is assumed that * `buchi_transition' and * `system_transition' initially point to * two transitions starting from * `buchi_state' and `system_state', * respectively. * * Returns: Nothing. Upon return, `buchi_transition' and * `system_transition' will either equal * `buchi_state.edges().end()' and `system_state.edges().end()', * respectively, or they will point to a pair of transitions * beginning from `buchi_state' and `system_state' such that * this pair of transitions corresponds to a transition starting * from the product state determined by `buchi_state' and * `system_state'. * * ------------------------------------------------------------------------- */ { const GraphEdgeContainer& buchi_transitions = buchi_state.edges(); const GraphEdgeContainer& system_transitions = system_state.edges(); ++system_transition; if (system_transition == system_transitions.end()) { do { ++buchi_transition; if (buchi_transition == buchi_transitions.end()) return; } while (!static_cast (*buchi_transition)->enabled (static_cast(system_state) .positiveAtoms(), statespace.numberOfPropositions())); system_transition = system_transitions.begin(); } } } #endif /* !STATESPACEPRODUCT_H */