From fc68c6734748f25f456545061899be4be380cc6a Mon Sep 17 00:00:00 2001
From: Jan Vesely <janvesely@janvesely.net>
Date: Thu, 24 Apr 2014 18:13:38 +0200
Subject: [PATCH] add rhdpda determinization with optimized s-component

---
 adeterminize/src/adeterminize.cpp             |  10 +-
 .../src/rhdpda/RhdpdaDeterminizer3.cpp        | 237 ++++++++++++++++++
 adeterminize/src/rhdpda/RhdpdaDeterminizer3.h | 131 ++++++++++
 3 files changed, 373 insertions(+), 5 deletions(-)
 create mode 100644 adeterminize/src/rhdpda/RhdpdaDeterminizer3.cpp
 create mode 100644 adeterminize/src/rhdpda/RhdpdaDeterminizer3.h

diff --git a/adeterminize/src/adeterminize.cpp b/adeterminize/src/adeterminize.cpp
index 5f0e608b44..6fc8bff09d 100644
--- a/adeterminize/src/adeterminize.cpp
+++ b/adeterminize/src/adeterminize.cpp
@@ -17,6 +17,7 @@
 #include "vpa/VpaDeterminizer3.h"
 #include "rhdpda/RhdpdaDeterminizer.h"
 #include "rhdpda/RhdpdaDeterminizer2.h"
+#include "rhdpda/RhdpdaDeterminizer3.h"
 
 using namespace std;
 using namespace automaton;
@@ -32,7 +33,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 2 versions (use numbers 1, 2). 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 also 3 versions (use numbers 1, 2 and 3). Default value is always number 1." << endl;
     cout << "  -h, --help \t Displays this help message." << endl;
     cout << endl;
 }
@@ -41,20 +42,19 @@ void printHelp() {
 Determinizer* getVpaDeterminizer(Automaton* automaton, string version) {
     if (version == "3") {
         return new vpa::VpaDeterminizer3((PDA*) automaton);
-
     } else if (version == "2") {
         return new vpa::VpaDeterminizer2((PDA*) automaton);
     }
-
     return new vpa::VpaDeterminizer((PDA*) automaton);
 }
 
 
 Determinizer* getRhdpdaDeterminizer(Automaton* automaton, string version) {
-    if (version == "2") {
+    if (version == "3") {
+        return new rhdpda::RhdpdaDeterminizer3((PDA*) automaton);
+    } else if (version == "2") {
         return new rhdpda::RhdpdaDeterminizer2((PDA*) automaton);
     }
-
     return new rhdpda::RhdpdaDeterminizer((PDA*) automaton);
 }
 
diff --git a/adeterminize/src/rhdpda/RhdpdaDeterminizer3.cpp b/adeterminize/src/rhdpda/RhdpdaDeterminizer3.cpp
new file mode 100644
index 0000000000..57ea354fbb
--- /dev/null
+++ b/adeterminize/src/rhdpda/RhdpdaDeterminizer3.cpp
@@ -0,0 +1,237 @@
+#include "RhdpdaDeterminizer3.h"
+
+namespace determinization {
+namespace rhdpda {
+
+
+void RhdpdaDeterminizer3::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 RhdpdaDeterminizer3::buildStackSymbolName(const SComponent& s, const RComponent& r, const Symbol& input)
+{
+    return RhdpdaUtils::buildStackSymbolName(s, r, input, *this->rdpda);
+}
+
+
+set<StateSymbolPair> RhdpdaDeterminizer3::combineStatesWithSymbol(const set<State>& states, const Symbol& symbol)
+{
+    return RhdpdaUtils::combineStatesWithSymbol(states, symbol);
+}
+
+
+const SComponent RhdpdaDeterminizer3::getSComponentWithPairsIdentity(const set<StateSymbolPair>& pairs)
+{
+    return RhdpdaUtils::getSComponentWithPairsIdentity(pairs);
+}
+
+
+const State& RhdpdaDeterminizer3::getOrCreateState(const SComponent& s, const RComponent& r)
+{
+    return RhdpdaUtils::getOrCreateState(s, r, this->states, *this->rdpda);
+}
+
+
+void RhdpdaDeterminizer3::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);
+    this->allRComponents = RhdpdaUtils::generateAllPossibleRComponents(this->allStateSymbolPairs);
+
+    Utils::copyInputAlphabet(*this->rhdpda, *this->rdpda);
+    this->divideTransitions();
+}
+
+
+RhdpdaDeterminizer3::RhdpdaDeterminizer3(PDA* rhdpda)
+{
+    this->rhdpda = rhdpda;
+}
+
+
+Automaton* RhdpdaDeterminizer3::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 RComponent& initialR(initialPairs);
+    const State& initialState = this->getOrCreateState(initialS, initialR);
+    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)));
+                    }
+                }
+            }
+            RComponent rPrimed;
+            RComponent& r = unmarkedStateData->r;
+            for (const auto& pair : r.pairs) {
+                const State& p = pair.state;
+                const Symbol& Y = pair.symbol;
+                for (const auto& transition : this->internalTransitions) {
+                    if (transition.getFrom() == p && transition.getInput() == a) {
+                        const State& q = transition.getTo();
+                        rPrimed.pairs.insert(StateSymbolPair(q, Y));
+                    }
+                }
+            }
+            if (sPrimed.pairsOfPairs.size() > 0 && rPrimed.pairs.size() > 0) {
+                const State& fromState = unmarkedStateData->state;
+                const State& toState = this->getOrCreateState(sPrimed, rPrimed);
+                const TransitionPDA transition(fromState, a, toState);
+                this->rdpda->addTransition(transition);
+            }
+        }
+        
+        // Push
+        for (const auto& a : this->rhdpda->getInputAlphabet()) {
+            RComponent rDoublePrimed;
+            RComponent& r = unmarkedStateData->r;
+            for (const auto& pair : r.pairs) {
+                const State& p = pair.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));
+                    }
+                }
+            }
+            SComponent sDoublePrimed = this->getSComponentWithPairsIdentity(rDoublePrimed.pairs);
+            SComponent& s = unmarkedStateData->s;
+            if (rDoublePrimed.pairs.size() > 0) {
+                const State& fromState = unmarkedStateData->state;
+                const State& toState = this->getOrCreateState(sDoublePrimed, rDoublePrimed);
+                string stackSymbolName = this->buildStackSymbolName(s, r, 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) {
+                    for (const auto& rPrimed : this->allRComponents) {
+                        RComponent rDoublePrimed;
+                        for (const auto& updateItem : update) {
+                            const State& p = updateItem.pair1.state;
+                            const State& q = updateItem.pair2.state;
+                            for (const auto& rPrimedPair : rPrimed.pairs) {
+                                if (rPrimedPair.state == p) {
+                                    const Symbol& Y = rPrimedPair.symbol;
+                                    rDoublePrimed.pairs.insert(StateSymbolPair(q, Y));
+                                }
+                            }
+                        }
+                        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 && rDoublePrimed.pairs.size() > 0) {
+                            const State& fromState = unmarkedStateData->state;
+                            const State& toState = this->getOrCreateState(sDoublePrimed, rDoublePrimed);
+                            string stackSymbolName = this->buildStackSymbolName(sPrimed, rPrimed, 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 RComponent& r = state.second.r;
+        for (const auto& pair : r.pairs) {
+            if (rhdpdaFinalStates.find(pair.state) != rhdpdaFinalStates.end()) {
+                isFinalState = true;
+            }
+        }
+        if (isFinalState) {
+            this->rdpda->addFinalState(state.second.state);
+        }
+    }
+
+    return this->rdpda;
+}
+
+
+}
+}
diff --git a/adeterminize/src/rhdpda/RhdpdaDeterminizer3.h b/adeterminize/src/rhdpda/RhdpdaDeterminizer3.h
new file mode 100644
index 0000000000..c111621be2
--- /dev/null
+++ b/adeterminize/src/rhdpda/RhdpdaDeterminizer3.h
@@ -0,0 +1,131 @@
+#ifndef RHDPDADETERMINZER3_H_
+#define RHDPDADETERMINZER3_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 second version of determinization algorithm on rhdpda.
+ */
+class RhdpdaDeterminizer3 : 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;
+
+        /** Vector with all possible R components of deterministic pda */
+        vector<RComponent> allRComponents;
+
+        /**
+         * Divides transitions of rhdpda into internal, push and pop transitions.
+         *
+         * @return void
+         */
+        void divideTransitions();
+
+        /**
+         * 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 RComponent& r, 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
+         * @param r R component of state
+         * @return state of deterministic pda
+         */
+        const State& getOrCreateState(const SComponent& s, const RComponent& r);
+
+        /**
+         * Runs some initializiation stuff before determinization algorithm.
+         */
+        void initDeterminization();
+
+    public:
+
+        /**
+         * @param rhdpda real-time height-deterministic pushdown automaton given for determinization
+         */
+        RhdpdaDeterminizer3(PDA* rhdpda);
+
+        /**
+         * Runs determinization algorithm on rhdpda given in constructor.
+         *
+         * @return real-time deterministic pushdown automaton
+         */
+        Automaton* determinize();
+
+};
+
+}
+}
+#endif
-- 
GitLab