From 1be54fa9b76abd439e1789f340ab5aeb5727c5e1 Mon Sep 17 00:00:00 2001 From: Jan Vesely <janvesely@janvesely.net> Date: Thu, 24 Apr 2014 18:45:10 +0200 Subject: [PATCH] add rhdpda determinization with removed r-component --- adeterminize/src/adeterminize.cpp | 7 +- .../src/rhdpda/RhdpdaDeterminizer4.cpp | 237 ++++++++++++++++++ adeterminize/src/rhdpda/RhdpdaDeterminizer4.h | 135 ++++++++++ adeterminize/src/rhdpda/RhdpdaStructs.h | 5 + 4 files changed, 382 insertions(+), 2 deletions(-) create mode 100644 adeterminize/src/rhdpda/RhdpdaDeterminizer4.cpp create mode 100644 adeterminize/src/rhdpda/RhdpdaDeterminizer4.h diff --git a/adeterminize/src/adeterminize.cpp b/adeterminize/src/adeterminize.cpp index 6fc8bff09d..890e48526d 100644 --- a/adeterminize/src/adeterminize.cpp +++ b/adeterminize/src/adeterminize.cpp @@ -18,6 +18,7 @@ #include "rhdpda/RhdpdaDeterminizer.h" #include "rhdpda/RhdpdaDeterminizer2.h" #include "rhdpda/RhdpdaDeterminizer3.h" +#include "rhdpda/RhdpdaDeterminizer4.h" using namespace std; using namespace automaton; @@ -33,7 +34,7 @@ void printHelp() { cout << "Usage: adeterminize -t TYPE [SWITCH...]" << endl; cout << "Possible arguments:" << endl; cout << " -t, --type=TYPE \t Specifies type of input automaton, possible values are 'FSM' for final-state machine, 'IDPDA' for input-driven pushdown automaton, 'VPA' for visible pushdown automaton and 'RHDPDA' for real-time height deterministic pushdown automaton." << endl; - cout << " -a, --algorithm=VERSION_OF_ALGORITHM \t Specifies version of algorithm. This argument works only with VPA or RHDPDA type. VPA determinization has 3 versions (use numbers 1, 2 and 3) and RHDPDA determinization has also 3 versions (use numbers 1, 2 and 3). Default value is always number 1." << endl; + cout << " -a, --algorithm=VERSION_OF_ALGORITHM \t Specifies version of algorithm. This argument works only with VPA or RHDPDA type. VPA determinization has 3 versions (use numbers 1, 2 and 3) and RHDPDA determinization has 4 versions (use numbers 1, 2, 3 and 4). Default value is always number 1." << endl; cout << " -h, --help \t Displays this help message." << endl; cout << endl; } @@ -50,7 +51,9 @@ Determinizer* getVpaDeterminizer(Automaton* automaton, string version) { Determinizer* getRhdpdaDeterminizer(Automaton* automaton, string version) { - if (version == "3") { + if (version == "4") { + return new rhdpda::RhdpdaDeterminizer4((PDA*) automaton); + } else if (version == "3") { return new rhdpda::RhdpdaDeterminizer3((PDA*) automaton); } else if (version == "2") { return new rhdpda::RhdpdaDeterminizer2((PDA*) automaton); diff --git a/adeterminize/src/rhdpda/RhdpdaDeterminizer4.cpp b/adeterminize/src/rhdpda/RhdpdaDeterminizer4.cpp new file mode 100644 index 0000000000..a14f23b5b4 --- /dev/null +++ b/adeterminize/src/rhdpda/RhdpdaDeterminizer4.cpp @@ -0,0 +1,237 @@ +#include "RhdpdaDeterminizer4.h" + +namespace determinization { +namespace rhdpda { + + +void RhdpdaDeterminizer4::divideTransitions() +{ + for (const auto& transition : this->rhdpda->getTransitions()) { + if (transition.getPush().size() == 1) { + this->pushTransitions.insert(transition); + } else if (transition.getPop().size() == 1) { + this->popTransitions.insert(transition); + } else { + this->internalTransitions.insert(transition); + } + } +} + + +string RhdpdaDeterminizer4::buildStateName(const SComponent& s) +{ + string name = "{"; + for (const auto& pairOfPairs : s.pairsOfPairs) { + if (&pairOfPairs != &(*begin(s.pairsOfPairs))) { + name += ", "; + } + name += "(" + RhdpdaUtils::buildPairName(pairOfPairs.pair1) + ", " + + RhdpdaUtils::buildPairName(pairOfPairs.pair2) + ")"; + } + return name + "}"; +} + + +string RhdpdaDeterminizer4::buildStackSymbolName(const SComponent& s, const Symbol& input) +{ + string name = "(" + this->buildStateName(s) + ")"; + name += ", " + input.getSymbol(); + try { + this->rdpda->addStackSymbol(name); + } catch (AutomatonException e) { + /* Stack symbol already exists */ + } + return name; +} + + +set<StateSymbolPair> RhdpdaDeterminizer4::combineStatesWithSymbol(const set<State>& states, const Symbol& symbol) +{ + return RhdpdaUtils::combineStatesWithSymbol(states, symbol); +} + + +const SComponent RhdpdaDeterminizer4::getSComponentWithPairsIdentity(const set<StateSymbolPair>& pairs) +{ + return RhdpdaUtils::getSComponentWithPairsIdentity(pairs); +} + + +const State& RhdpdaDeterminizer4::getOrCreateState(const SComponent& s) +{ + string stateName = this->buildStateName(s); + map<string, StateData>::iterator statesIter = this->states.find(stateName); + if (statesIter != this->states.end()) { + return statesIter->second.state; + } + State state(stateName); + StateData stateData(state, s); + StateData& insertedData = this->states.insert(pair<string, StateData>(stateName, stateData)).first->second; + this->rdpda->addState(state); + return insertedData.state; +} + + +void RhdpdaDeterminizer4::initDeterminization() +{ + this->states.clear(); + this->internalTransitions.clear(); + this->pushTransitions.clear(); + this->popTransitions.clear(); + + this->allStateSymbolPairs = RhdpdaUtils::buildAllStateSymbolPairs(*this->rhdpda); + this->allSComponents = RhdpdaUtils::generateAllPossibleSComponents(this->allStateSymbolPairs); + + Utils::copyInputAlphabet(*this->rhdpda, *this->rdpda); + this->divideTransitions(); +} + + +RhdpdaDeterminizer4::RhdpdaDeterminizer4(PDA* rhdpda) +{ + this->rhdpda = rhdpda; +} + + +Automaton* RhdpdaDeterminizer4::determinize() +{ + const Symbol& BOTTOM_OF_STACK_SYMBOL = RhdpdaUtils::BOTTOM_OF_STACK_SYMBOL; + + this->rdpda = new PDA(); + this->initDeterminization(); + + set<StateSymbolPair> initialPairs = this->combineStatesWithSymbol(this->rhdpda->getInitialStates(), BOTTOM_OF_STACK_SYMBOL); + const SComponent& initialS = this->getSComponentWithPairsIdentity(initialPairs); + const State& initialState = this->getOrCreateState(initialS); + this->rdpda->addInitialState(initialState); + + while (true) { + StateData* unmarkedStateData = RhdpdaUtils::getUnmarkedState(this->states); + if (unmarkedStateData == NULL) { + break; + } + + // Internal + for (const auto& a : this->rhdpda->getInputAlphabet()) { + SComponent sPrimed; + SComponent& s = unmarkedStateData->s; + for (const auto& pairOfPairs : s.pairsOfPairs) { + const StateSymbolPair& x = pairOfPairs.pair1; + const State& r = pairOfPairs.pair2.state; + const Symbol& Y = pairOfPairs.pair2.symbol; + for (const auto& transition : this->internalTransitions) { + if (transition.getFrom() == r && transition.getInput() == a) { + const State& q = transition.getTo(); + sPrimed.pairsOfPairs.insert(PairOfPairs(x, StateSymbolPair(q, Y))); + } + } + } + if (sPrimed.pairsOfPairs.size() > 0) { + const State& fromState = unmarkedStateData->state; + const State& toState = this->getOrCreateState(sPrimed); + const TransitionPDA transition(fromState, a, toState); + this->rdpda->addTransition(transition); + } + } + + // Push + for (const auto& a : this->rhdpda->getInputAlphabet()) { + RComponent rDoublePrimed; + SComponent& s = unmarkedStateData->s; + for (const auto& pairOfPairs : s.pairsOfPairs) { + const State& p = pairOfPairs.pair2.state; + for (const auto& transition : this->pushTransitions) { + if (transition.getFrom() == p && transition.getInput() == a) { + const State& q = transition.getTo(); + const Symbol& Z = transition.getPush().front(); + rDoublePrimed.pairs.insert(StateSymbolPair(q, Z)); + } + } + } + if (rDoublePrimed.pairs.size() > 0) { + const State& fromState = unmarkedStateData->state; + SComponent sDoublePrimed = this->getSComponentWithPairsIdentity(rDoublePrimed.pairs); + const State& toState = this->getOrCreateState(sDoublePrimed); + string stackSymbolName = this->buildStackSymbolName(s, a); + list<Symbol> pop = {}; + list<Symbol> push = {Symbol(stackSymbolName)}; + const TransitionPDA transition(fromState, a, toState, pop, push); + this->rdpda->addTransition(transition); + } + } + + // Pop + for (const auto& a : this->rhdpda->getInputAlphabet()) { + for (const auto& b : this->rhdpda->getInputAlphabet()) { + SComponent& s = unmarkedStateData->s; + set<PairOfPairs> update; + for (const auto& pairOfPairs : s.pairsOfPairs) { + const State& r = pairOfPairs.pair1.state; + const Symbol& Z = pairOfPairs.pair1.symbol; + const State& rPrimed = pairOfPairs.pair2.state; + if (pairOfPairs.pair2.symbol == Z) { + for (const auto& pushTransition : this->pushTransitions) { + for (const auto& popTransition : this->popTransitions) { + const State& p = pushTransition.getFrom(); + const State& q = popTransition.getTo(); + if (pushTransition.getInput() == a && pushTransition.getTo() == r && + popTransition.getInput() == b && popTransition.getFrom() == rPrimed && + pushTransition.getPush().front() == Z && popTransition.getPop().front() == Z) { + StateSymbolPair pair1(p, Z); + StateSymbolPair pair2(q, Z); + update.insert(PairOfPairs(pair1, pair2)); + } + } + } + } + } + if (update.size() == 0) { + continue; + } + for (const auto& sPrimed : this->allSComponents) { + SComponent sDoublePrimed; + for (const auto& updateItem : update) { + const State& p = updateItem.pair1.state; + const State& q = updateItem.pair2.state; + for (const auto& sPrimedPair : sPrimed.pairsOfPairs) { + if (sPrimedPair.pair2.state == p) { + const StateSymbolPair& x = sPrimedPair.pair1; + const Symbol& Y = sPrimedPair.pair2.symbol; + sDoublePrimed.pairsOfPairs.insert(PairOfPairs(x, StateSymbolPair(q, Y))); + } + } + } + if (sDoublePrimed.pairsOfPairs.size() > 0) { + const State& fromState = unmarkedStateData->state; + const State& toState = this->getOrCreateState(sDoublePrimed); + string stackSymbolName = this->buildStackSymbolName(sPrimed, a); + list<Symbol> pop = {Symbol(stackSymbolName)}; + list<Symbol> push = {}; + const TransitionPDA transition(fromState, b, toState, pop, push); + this->rdpda->addTransition(transition); + } + } + } + } + } + + const set<State>& rhdpdaFinalStates = this->rhdpda->getFinalStates(); + for (const auto& state : this->states) { + bool isFinalState = false; + const SComponent& s = state.second.s; + for (const auto& pairOfPairs : s.pairsOfPairs) { + if (rhdpdaFinalStates.find(pairOfPairs.pair2.state) != rhdpdaFinalStates.end()) { + isFinalState = true; + } + } + if (isFinalState) { + this->rdpda->addFinalState(state.second.state); + } + } + + return this->rdpda; +} + + +} +} diff --git a/adeterminize/src/rhdpda/RhdpdaDeterminizer4.h b/adeterminize/src/rhdpda/RhdpdaDeterminizer4.h new file mode 100644 index 0000000000..1df0da7bb4 --- /dev/null +++ b/adeterminize/src/rhdpda/RhdpdaDeterminizer4.h @@ -0,0 +1,135 @@ +#ifndef RHDPDADETERMINZER4_H_ +#define RHDPDADETERMINZER4_H_ + +#include <string> +#include <set> +#include <map> +#include <vector> + +#include "automaton/PDA/PDA.h" +#include "automaton/Transition.h" +#include "automaton/exception/AutomatonException.h" +#include "alphabet/Symbol.h" + +#include "../common/Utils.h" +#include "../Determinizer.h" +#include "RhdpdaUtils.h" +#include "RhdpdaStructs.h" + +using namespace std; +using namespace automaton; +using namespace alphabet; +using namespace determinization; + +namespace determinization { +namespace rhdpda { + +/** + * Class for running fourth version of determinization algorithm on rhdpda. + */ +class RhdpdaDeterminizer4 : public Determinizer +{ + + private: + + /** Real-time height-deterministic pushdown automaton */ + PDA* rhdpda; + + /** Real-time deterministic pushdown automaton */ + PDA* rdpda; + + /** Map of states of deterministic pda, where key is the name of state and value is data about this state */ + map<string, StateData> states; + + /** Set of internal transitions from rhdpda */ + set<TransitionPDA> internalTransitions; + + /** Set of push transitions from rhdpda */ + set<TransitionPDA> pushTransitions; + + /** Set of pop transitions from rhdpda */ + set<TransitionPDA> popTransitions; + + /** Set of all possible pairs of states and stack symbols */ + set<StateSymbolPair> allStateSymbolPairs; + + /** Vector with all possible S components of deterministic pda */ + vector<SComponent> allSComponents; + + /** + * Divides transitions of rhdpda into internal, push and pop transitions. + * + * @return void + */ + void divideTransitions(); + + /** + * Returns name of state of deterministic pda which is created from given S. + * + * @param s S component of state + * @return name of state + */ + string buildStateName(const SComponent& s); + + /** + * Returns name of stack symbol of deterministic pda which is created from given S and R component and input symbol. + * This method also ensures that this stack symbol is already added into deterministic pda. + * + * @param s S component of stack symbol + * @param r R component of stack symbol + * @param input input symbol + * @return name of stack symbol + */ + string buildStackSymbolName(const SComponent& s, const Symbol& input); + + /** + * Returns state and symbol pairs that are created by combining state from given set of states and given symbol. + * + * @param states + * @param symbol + * @return state and symbol pairs that are created by combining given states and symbol + */ + set<StateSymbolPair> combineStatesWithSymbol(const set<State>& states, const Symbol& symbol); + + /** + * Returns S component that contains pairs where both elements are same. These pairs are created from given set + * of state and symbol pairs. + * + * @param pairs set of state and symbol pairs from which to create identity pairs + * @return pairs where both elements are same + */ + const SComponent getSComponentWithPairsIdentity(const set<StateSymbolPair>& pairs); + + /** + * Returns existing state from states map, if there is one with same name, or creates new one and adds it into + * states map and deterministic pda. + * + * @param s S component of state + * @return state of deterministic pda + */ + const State& getOrCreateState(const SComponent& s); + + /** + * Runs some initializiation stuff before determinization algorithm. + */ + void initDeterminization(); + + public: + + /** + * @param rhdpda real-time height-deterministic pushdown automaton given for determinization + */ + RhdpdaDeterminizer4(PDA* rhdpda); + + /** + * Runs determinization algorithm on rhdpda given in constructor. + * + * @return real-time deterministic pushdown automaton + */ + Automaton* determinize(); + +}; + +} +} +#endif diff --git a/adeterminize/src/rhdpda/RhdpdaStructs.h b/adeterminize/src/rhdpda/RhdpdaStructs.h index 238ff5ea96..2db3c2b746 100644 --- a/adeterminize/src/rhdpda/RhdpdaStructs.h +++ b/adeterminize/src/rhdpda/RhdpdaStructs.h @@ -114,6 +114,11 @@ struct StateData s(s), r(r), isMarked(false) {} + + StateData(const State& state, const SComponent& s) + : state(state), + s(s), + isMarked(false) {} }; -- GitLab