Skip to content
Snippets Groups Projects
Commit 9dcfba2a authored by Jan Trávníček's avatar Jan Trávníček
Browse files

untested vpa determinisation

parent 9118a740
No related branches found
No related tags found
No related merge requests found
#include "VpaDeterminizer3.h"
namespace determinization {
namespace vpa {
string VpaDeterminizer3::buildStateName(const SComponent& s)
{
string name = "{";
for (const auto& statesPair : s.statesPairs) {
if (&statesPair != &(*begin(s.statesPairs))) {
name += ", ";
}
name += "('" + statesPair.state1.getName() + "', '" + statesPair.state2.getName() + "')";
}
name += "}";
return name;
}
string VpaDeterminizer3::buildStackSymbolName(const SComponent& s, const Symbol& input)
{
string name = "(" + this->buildStateName(s) + ")";
name += ", " + input.getSymbol();
try {
this->dvpa->addStackSymbol(name);
} catch (AutomatonException e) {
/* Stack symbol already exists */
}
return name;
}
const State& VpaDeterminizer3::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->dvpa->addState(state);
return insertedData.state;
}
const SComponent VpaDeterminizer3::getSComponentWithStatesIdentity(const set<State>& states)
{
return VpaUtils::getSComponentWithStatesIdentity(states);
}
void VpaDeterminizer3::initDeterminization()
{
this->states.clear();
this->internalSymbols.clear();
this->callSymbols.clear();
this->returnSymbols.clear();
Utils::copyInputAlphabet(*this->nvpa, *this->dvpa);
VpaUtils::divideInputAlphabet(*this->nvpa, this->internalSymbols, this->callSymbols, this->returnSymbols);
this->allSComponents = VpaUtils::generateAllSComponents(this->nvpa->getStates());
this->dvpa->addStackSymbol(VpaUtils::BOTTOM_OF_STACK_SYMBOL);
}
VpaDeterminizer3::VpaDeterminizer3(PDA* nvpa)
{
this->nvpa = nvpa;
}
Automaton* VpaDeterminizer3::determinize()
{
this->dvpa = new PDA();
this->initDeterminization();
const SComponent& initialS = this->getSComponentWithStatesIdentity(this->nvpa->getInitialStates());
const State& initialState = this->getOrCreateState(initialS);
this->dvpa->addInitialState(initialState);
while (true) {
StateData* unmarkedStateData = VpaUtils::getUnmarkedState(states);
if (unmarkedStateData == NULL) {
break;
}
// Internal symbols
for (const auto& internalSymbol : internalSymbols) {
SComponent sPrimed;
SComponent& s = unmarkedStateData->s;
for (const auto& statesPair : s.statesPairs) {
const State& q = statesPair.state1;
const State& qDoublePrimed = statesPair.state2;
for (const auto& transition : this->nvpa->getTransitions()) {
if (transition.getFrom() == qDoublePrimed && transition.getInput() == internalSymbol) {
const State& qPrimed = transition.getTo();
sPrimed.statesPairs.insert(StatesPair(q, qPrimed));
}
}
}
if (sPrimed.statesPairs.size() > 0) {
const State& fromState = unmarkedStateData->state;
const State& toState = this->getOrCreateState(sPrimed);
const TransitionPDA transition(fromState, internalSymbol, toState);
this->dvpa->addTransition(transition);
}
}
// Call symbols
for (const auto& callSymbol : callSymbols) {
RComponent rPrimed;
SComponent& s = unmarkedStateData->s;
for (const auto& statesPair : s.statesPairs) {
const State& q = statesPair.state2;
for (const auto& transition : this->nvpa->getTransitions()) {
if (transition.getFrom() == q && transition.getInput() == callSymbol) {
const State& qPrimed = transition.getTo();
rPrimed.states.insert(qPrimed);
}
}
}
if (rPrimed.states.size() > 0) {
const SComponent& sPrimed = this->getSComponentWithStatesIdentity(rPrimed.states);
const State& fromState = unmarkedStateData->state;
const State& toState = this->getOrCreateState(sPrimed);
string stackSymbolName = this->buildStackSymbolName(s, callSymbol);
list<Symbol> pop = {};
list<Symbol> push = {Symbol(stackSymbolName)};
const TransitionPDA transition(fromState, callSymbol, toState, pop, push);
this->dvpa->addTransition(transition);
}
}
// Return symbols
for (const auto& returnSymbol : returnSymbols) {
SComponent& s = unmarkedStateData->s;
// Empty stack
list<Symbol> bottomOfStack = {VpaUtils::BOTTOM_OF_STACK_SYMBOL};
SComponent sPrimed;
for (const auto& statesPair : s.statesPairs) {
const State& q = statesPair.state1;
const State& qDoublePrimed = statesPair.state2;
for (const auto& transition : this->nvpa->getTransitions()) {
if (transition.getFrom() == qDoublePrimed && transition.getInput() == returnSymbol &&
transition.getPop() == bottomOfStack) {
const State& qPrimed = transition.getTo();
sPrimed.statesPairs.insert(StatesPair(q, qPrimed));
}
}
}
if (sPrimed.statesPairs.size() > 0) {
const State& fromState = unmarkedStateData->state;
const State& toState = this->getOrCreateState(sPrimed);
list<Symbol> pop = {VpaUtils::BOTTOM_OF_STACK_SYMBOL};
list<Symbol> push = {};
const TransitionPDA transition(fromState, returnSymbol, toState, pop, push);
this->dvpa->addTransition(transition);
}
// Otherwise
for (const auto& callSymbol : callSymbols) {
set<StatesPair> update;
for (const auto& sPair : s.statesPairs) {
const State& q1 = sPair.state1;
const State& q2 = sPair.state2;
for (const auto& transitionPush : this->nvpa->getTransitions()) {
for (const auto& transitionPop : this->nvpa->getTransitions()) {
const State& q = transitionPush.getFrom();
const State& qPrimed = transitionPop.getTo();
if (transitionPush.getInput() == callSymbol && transitionPush.getTo() == q1 &&
transitionPop.getInput() == returnSymbol && transitionPop.getFrom() == q2 &&
transitionPush.getPush() == transitionPop.getPop()) {
update.insert(StatesPair(q, qPrimed));
}
}
}
}
if (update.size() == 0) {
continue;
}
for (const auto& sPrimed : this->allSComponents) {
SComponent sDoublePrimed;
for (const auto& updateItem : update) {
const State& q3 = updateItem.state1;
const State& qPrimed = updateItem.state2;
for (const auto& sPrimedPair : sPrimed.statesPairs) {
if (sPrimedPair.state2 == q3) {
const State& q = sPrimedPair.state1;
sDoublePrimed.statesPairs.insert(StatesPair(q, qPrimed));
}
}
}
if (sDoublePrimed.statesPairs.size() > 0) {
const State& fromState = unmarkedStateData->state;
const State& toState = this->getOrCreateState(sDoublePrimed);
string stackSymbolName = this->buildStackSymbolName(sPrimed, callSymbol);
list<Symbol> pop = {Symbol(stackSymbolName)};
list<Symbol> push = {};
const TransitionPDA transition(fromState, returnSymbol, toState, pop, push);
this->dvpa->addTransition(transition);
}
}
}
}
}
// Final states
for (const auto& stateIter : states) {
const StateData& stateData = stateIter.second;
set<State> secondStates;
for (const auto& sPair : stateData.s.statesPairs) {
secondStates.insert(sPair.state2);
}
if (Utils::containFinalState(secondStates, *this->nvpa)) {
this->dvpa->addFinalState(stateData.state);
}
}
return this->dvpa;
}
}
}
#ifndef VPADETERMINIZER3_H_
#define VPADETERMINIZER3_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 "VpaUtils.h"
#include "VpaStructs.h"
using namespace std;
using namespace automaton;
using namespace alphabet;
namespace determinization {
namespace vpa {
/**
* Class for running third version of determinization algorithm on vpa.
*/
class VpaDeterminizer3 : public Determinizer
{
private:
/** Nondeterministic visibly pushdown automaton */
PDA* nvpa;
/** Deterministic visibly pushdown automaton */
PDA* dvpa;
/** Map of states of deterministic vpa, where key is the name of state and value is data about this state */
map<string, StateData> states;
/** Set of internal input symbols from nondeterministic automaton */
set<Symbol> internalSymbols;
/** Set of call input symbols from nondeterministic automaton */
set<Symbol> callSymbols;
/** Set of return input symbols from nondeterministic automaton */
set<Symbol> returnSymbols;
/** Vector with all possible S components of deterministic vpa */
vector<SComponent> allSComponents;
/**
* Returns name of state of deterministic vpa which is created from given S component.
*
* @param s S component of state
* @return name of state
*/
string buildStateName(const SComponent& s);
/**
* Returns name of stack symbol of deterministic vpa which is created from given S component and input symbol.
* This method also ensures that this stack symbol is already added into deterministic vpa.
*
* @param s S component of stack symbol
* @param input input symbol
* @return name of stack symbol
*/
string buildStackSymbolName(const SComponent& s, const Symbol& input);
/**
* 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 vpa.
*
* @param s S component of state
* @return state of deterministic vpa
*/
const State& getOrCreateState(const SComponent& s);
/**
* Returns S component that contains pairs where states are same.
*
* @param states set of states from which to create pairs
* @return pairs where states are same
*/
const SComponent getSComponentWithStatesIdentity(const set<State>& states);
/**
* Runs some initializiation stuff before determinization algorithm.
*/
void initDeterminization();
public:
/**
* @param nvpa nondeterministic visibly pushdown automaton given for determinization
*/
VpaDeterminizer3(PDA* nvpa);
/**
* Runs determinization algorithm on nondeterministic vpa given in constructor.
*
* @return deterministic visibly pushdown automaton
*/
Automaton* determinize();
};
}
}
#endif
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
#include "exception/AlibException.h" #include "exception/AlibException.h"
   
#include "determinize/nfa/NFADeterminizer.h" #include "determinize/nfa/NFADeterminizer.h"
//#include "idpda/IdpdaDeterminizer.h" #include "determinize/idpda/IDPDADeterminizer.h"
#include "determinize/vpa/VPADeterminizer.h"
//#include "vpa/VpaDeterminizer.h" //#include "vpa/VpaDeterminizer.h"
//#include "vpa/VpaDeterminizer2.h" //#include "vpa/VpaDeterminizer2.h"
//#include "vpa/VpaDeterminizer3.h" //#include "vpa/VpaDeterminizer3.h"
...@@ -113,14 +114,19 @@ int main(int argc, char** argv) { ...@@ -113,14 +114,19 @@ int main(int argc, char** argv) {
} else { } else {
throw exception::AlibException("Unsupported formalism"); throw exception::AlibException("Unsupported formalism");
} }
}
/* } else if (type == TYPE_IDPDA) {
return new idpda::IdpdaDeterminizer((PDA*) automaton);
   
} else if (type == TYPE_IDPDA) {
automaton::InputDrivenNPDA npda = alib::DataFactory::fromTokens<automaton::InputDrivenNPDA>(tokens);
automaton::DPDA dpda = determinize::IDPDADeterminizer::determinize(npda);
alib::DataFactory::toStdout(dpda);
return 0;
} else if (type == TYPE_VPA) { } else if (type == TYPE_VPA) {
return getVpaDeterminizer(automaton, version); automaton::VisiblyPushdownNPDA npda = alib::DataFactory::fromTokens<automaton::VisiblyPushdownNPDA>(tokens);
automaton::VisiblyPushdownNPDA dpda = determinize::VPADeterminizer::determinize(npda);
alib::DataFactory::toStdout(dpda);
return 0;
}
/*
} else if (type == TYPE_RHDPDA) { } else if (type == TYPE_RHDPDA) {
return getRhdpdaDeterminizer(automaton, version); return getRhdpdaDeterminizer(automaton, version);
}*/ }*/
......
#include "VPADeterminizer.h"
#include "automaton/common/State.h"
#include "alphabet/Symbol.h"
#include "alphabet/LabeledSymbol.h"
#include "label/Label.h"
#include "label/LabelSetLabel.h"
#include "label/LabelPairLabel.h"
namespace determinize {
label::Label VPADeterminizer::packToDVPAStateLabel(const std::set<std::pair<label::Label, label::Label>>& data) {
std::set<label::Label> res;
for(const auto& subData : data) {
res.insert(label::Label(label::LabelPairLabel(subData)));
}
return label::Label(label::LabelSetLabel(res));
}
std::set<std::pair<label::Label, label::Label>> VPADeterminizer::unpackFromDVPAStateLabel(const label::Label& data) {
std::set<std::pair<label::Label, label::Label>> res;
for (const auto& subData : static_cast<const label::LabelSetLabel&>(data.getData()).getData()) {
res.insert(static_cast<const label::LabelPairLabel&>(subData.getData()).getData());
}
return res;
}
label::Label VPADeterminizer::packToDVPAStackSymbolLabel(const std::pair<std::set<std::pair<label::Label, label::Label>>, label::Label>& data) {
std::set<label::Label> res;
for(const auto& subData : data.first) {
res.insert(label::Label(label::LabelPairLabel(subData)));
}
return label::Label(label::LabelPairLabel(std::make_pair(label::Label(label::LabelSetLabel(res)), data.second)));
}
std::pair<std::set<std::pair<label::Label, label::Label>>, label::Label> VPADeterminizer::unpackFromDVPAStackSymbolLabel(const label::Label& data) {
std::set<std::pair<label::Label, label::Label>> res;
for (const auto& subData : static_cast<const label::LabelSetLabel&>(static_cast<const label::LabelPairLabel&>(data.getData()).getData().first.getData()).getData()) {
res.insert(static_cast<const label::LabelPairLabel&>(subData.getData()).getData());
}
return std::make_pair(res, static_cast<const label::LabelPairLabel&>(data.getData()).getData().second);
}
void addRetTransition(const automaton::State& from, const alphabet::Symbol& input, const alphabet::Symbol& dvpdaSymbol, const automaton::State& to, automaton::VisiblyPushdownNPDA& deterministic) {
deterministic.addState(from);
deterministic.addState(to);
deterministic.addStackSymbol(dvpdaSymbol);
deterministic.addTransition(from, input, dvpdaSymbol, to);
}
void retInitial(const automaton::State& state, const alphabet::Symbol& pdaSymbol, const alphabet::Symbol& input, const automaton::VisiblyPushdownNPDA& nondeterministic, automaton::VisiblyPushdownNPDA& deterministic) {
std::set<std::pair<label::Label, label::Label>> S = VPADeterminizer::unpackFromDVPAStateLabel(state.getName());
std::set<std::pair<label::Label, label::Label>> S1;
for(const auto& entry : S) {
const label::Label& q = entry.first;
const label::Label& q2 = entry.second;
for(const auto& transition : nondeterministic.getReturnTransitions()) {
if(q2 != std::get<0>(transition.first).getName()) continue;
if(input != std::get<1>(transition.first)) continue;
if(nondeterministic.getBottomOfTheStackSymbol() != std::get<2>(transition.first)) continue;
for(const auto& to : transition.second) {
const label::Label& q1 = to.getName();
S1.insert(std::make_pair(q, q1));
}
}
}
addRetTransition(state, input, pdaSymbol, automaton::State(VPADeterminizer::packToDVPAStateLabel(S1)), deterministic);
}
void ret(const automaton::State& state, const alphabet::Symbol& pdaSymbol, const alphabet::Symbol& input, const automaton::VisiblyPushdownNPDA& nondeterministic, automaton::VisiblyPushdownNPDA& deterministic) {
std::set<std::pair<label::Label, label::Label>> S = VPADeterminizer::unpackFromDVPAStateLabel(state.getName());
std::pair<std::set<std::pair<label::Label, label::Label>>, label::Label> pdaSymbolUnpack = VPADeterminizer::unpackFromDVPAStackSymbolLabel(static_cast<const alphabet::LabeledSymbol&>(pdaSymbol.getData()).getLabel());
const std::set<std::pair<label::Label, label::Label>>& S1 = pdaSymbolUnpack.first;
std::set<std::pair<label::Label, label::Label>> update;
for(const auto& transition : nondeterministic.getCallTransitions()) {
if(pdaSymbolUnpack.second != static_cast<const alphabet::LabeledSymbol&>(std::get<1>(transition.first).getData()).getLabel()) continue;
const label::Label& q = std::get<0>(transition.first).getName();
for(const auto& to : transition.second) {
const label::Label q1 = to.first.getName();
const alphabet::Symbol& gamma = to.second;
for(const auto& entry : S) {
if(q1 != entry.first) continue;
const label::Label& q2 = entry.second;
for(const auto& transition2 : nondeterministic.getReturnTransitions()) {
if(q2 != std::get<0>(transition2.first).getName()) continue;
if(input != std::get<1>(transition2.first)) continue;
if(gamma != std::get<2>(transition2.first)) continue;
for(const auto& to2 : transition2.second) {
const label::Label& qI = to2.getName();
update.insert(std::make_pair(q, qI));
}
}
}
}
}
std::set<std::pair<label::Label, label::Label>> S2;
for(const auto& entry : S1) {
const label::Label& q = entry.first;
const label::Label& q3 = entry.second;
for(const auto& entry2 : update) {
if(q3 != entry2.first) continue;
const label::Label& qI = entry2.second;
S2.insert(std::make_pair(q, qI));
}
}
addRetTransition(state, input, pdaSymbol, automaton::State(VPADeterminizer::packToDVPAStateLabel(S2)), deterministic);
}
void addCallTransition(const automaton::State& from, const alphabet::Symbol& input, const automaton::State& to, const alphabet::Symbol& dvpdaSymbol, automaton::VisiblyPushdownNPDA& deterministic) {
deterministic.addState(from);
deterministic.addState(to);
deterministic.addStackSymbol(dvpdaSymbol);
deterministic.addTransition(from, input, to, dvpdaSymbol);
}
std::set<label::Label> retrieveDSubSet(const std::set<std::pair<label::Label, label::Label>>& localOperation) {
std::set<label::Label> id;
for(const auto& entry : localOperation) {
id.insert(entry.second);
}
return id;
}
std::set<std::pair<label::Label, label::Label>> createIdentity(std::set<label::Label> states) {
std::set<std::pair<label::Label, label::Label>> id;
for(const label::Label& state : states) {
id.insert(std::make_pair(state, state));
}
return id;
}
void call(const automaton::State& state, const alphabet::Symbol& input, const automaton::VisiblyPushdownNPDA& nondeterministic, automaton::VisiblyPushdownNPDA& deterministic) {
std::set<std::pair<label::Label, label::Label>> S = VPADeterminizer::unpackFromDVPAStateLabel(state.getName());
std::set<label::Label> R = retrieveDSubSet(S);
std::set<label::Label> R1;
for(const label::Label& q : R) {
for(const auto& transition : nondeterministic.getCallTransitions()) {
if(q != transition.first.first.getName()) continue;
if(input != transition.first.second) continue;
for(const auto& to : transition.second) {
const label::Label& q1 = to.first.getName();
R1.insert(q1);
}
}
}
const label::Label& inputLabel = static_cast<const alphabet::LabeledSymbol&>(input.getData()).getLabel();
addCallTransition(state, input, automaton::State(VPADeterminizer::packToDVPAStateLabel(createIdentity(R1))), alphabet::Symbol(alphabet::LabeledSymbol(VPADeterminizer::packToDVPAStackSymbolLabel(std::make_pair(S, inputLabel)))), deterministic);
}
void addLocalTransition(const automaton::State& from, const alphabet::Symbol& input, const automaton::State& to, automaton::VisiblyPushdownNPDA& deterministic) {
deterministic.addState(from);
deterministic.addState(to);
deterministic.addTransition(from, input, to);
}
void local(const automaton::State& state, const alphabet::Symbol& input, const automaton::VisiblyPushdownNPDA& nondeterministic, automaton::VisiblyPushdownNPDA& deterministic) {
std::set<std::pair<label::Label, label::Label>> S = VPADeterminizer::unpackFromDVPAStateLabel(state.getName());
std::set<std::pair<label::Label, label::Label>> S1;
for(const auto& entry : S) {
label::Label q = entry.first;
label::Label q2 = entry.second;
for(const auto& transition : nondeterministic.getLocalTransitions()) {
if(q2 != transition.first.first.getName()) continue;
if(input != transition.first.second) continue;
for(const auto& to : transition.second) {
label::Label q1 = to.getName();
S1.insert(std::make_pair(q, q1));
}
}
}
addLocalTransition(state, input, automaton::State(VPADeterminizer::packToDVPAStateLabel(S1)), deterministic);
}
const automaton::State* existsDirtyState(const automaton::VisiblyPushdownNPDA& d) {
for(const automaton::State& state : d.getStates()) {
const label::Label& stateLabel = state.getName();
for(const auto& transition : d.getCallTransitions()) {
if(stateLabel != transition.first.first.getName()) continue;
goto continue2;
}
return &state;
continue2: while(false);
}
return NULL;
}
std::set<label::Label> localClosure(std::set<label::Label> states, const automaton::VisiblyPushdownNPDA& d) {
std::set<label::Label> newStates;
for(const label::Label& state : states) {
for(const auto& transition : d.getLocalTransitions()) {
if(!transition.second.count(automaton::State(state))) continue;
newStates.insert(transition.first.first.getName());
}
for(const auto& transition : d.getReturnTransitions()) {
if(!transition.second.count(automaton::State(state))) continue;
const alphabet::Symbol& popSymbol = std::get<2>(transition.first);
const label::Label& popSymbolLabel = static_cast<const alphabet::LabeledSymbol>(popSymbol.getData()).getLabel();
const label::Label& statePart = static_cast<const label::LabelPairLabel&>(popSymbolLabel.getData()).getData().first;
newStates.insert(statePart);
}
}
if(states == newStates) return states;
return localClosure(newStates, d);
}
std::pair<label::Label, alphabet::Symbol>* existsDirtyStateSymbol(const automaton::VisiblyPushdownNPDA& d) {
for(const automaton::State& state : d.getStates()) {
const label::Label& stateLabel = state.getName();
std::set<label::Label> lc = localClosure(std::set<label::Label> {stateLabel}, d);
std::set<alphabet::Symbol> topSymbols;
for(const label::Label& localState : lc) {
for(const auto& transition : d.getCallTransitions()) {
for(const auto& to : transition.second) {
if(localState != to.first.getName()) continue;
topSymbols.insert(to.second);
}
}
if(d.getInitialStates().count(localState)) {
topSymbols.insert(d.getBottomOfTheStackSymbol());
}
}
for(const auto& transition : d.getReturnTransitions()) {
if(stateLabel != std::get<0>(transition.first).getName()) continue;
topSymbols.erase(std::get<2>(transition.first));
}
if(!topSymbols.empty()) return new std::pair<label::Label, alphabet::Symbol>(stateLabel, *topSymbols.begin());
}
return NULL;
}
std::set<label::Label> retrieveLabels(std::set<automaton::State> states) {
std::set<label::Label> labels;
for(const automaton::State& state : states) {
labels.insert(state.getName());
}
return labels;
}
automaton::VisiblyPushdownNPDA VPADeterminizer::determinize(const automaton::VisiblyPushdownNPDA& n) {
automaton::VisiblyPushdownNPDA d(n.getBottomOfTheStackSymbol());
d.setCallInputSymbols(n.getCallInputAlphabet());
d.setLocalInputSymbols(n.getLocalInputAlphabet());
d.setReturnInputSymbols(n.getReturnInputAlphabet());
label::Label initialLabel = VPADeterminizer::packToDVPAStateLabel(createIdentity(retrieveLabels(n.getInitialStates())));
d.addState(automaton::State(initialLabel));
d.addInitialState(automaton::State(initialLabel));
for(;;) {
std::pair<label::Label, alphabet::Symbol>* stateSymbol = existsDirtyStateSymbol(d);
const automaton::State* state = existsDirtyState(d);
if(stateSymbol != NULL) {
for(alphabet::Symbol symbol : n.getReturnInputAlphabet()) {
if(stateSymbol->second == d.getBottomOfTheStackSymbol()) {
retInitial(stateSymbol->first, stateSymbol->second, symbol, n, d);
} else {
ret(stateSymbol->first, stateSymbol->second, symbol, n, d);
}
}
delete stateSymbol; //TODO remove this...
} else if(state != NULL) {
for(alphabet::Symbol symbol : n.getLocalInputAlphabet()) {
local(*state, symbol, n, d);
}
for(alphabet::Symbol symbol : n.getCallInputAlphabet()) {
call(*state, symbol, n, d);
}
} else {
break;
}
}
std::set<label::Label> fin = retrieveLabels(n.getFinalStates());
for(automaton::State state : d.getStates()) {
std::set<label::Label> labels = retrieveDSubSet(VPADeterminizer::unpackFromDVPAStateLabel(state.getName()));
std::set<label::Label> finalLabels(fin);
finalLabels.erase(labels.begin(), labels.end());
if(!finalLabels.empty()) {
d.addFinalState(state);
}
}
return d;
}
}
#ifndef VPADETERMINIZER_H_
#define VPADETERMINIZER_H_
#include "automaton/PDA/VisiblyPushdownNPDA.h"
namespace determinize {
/**
* Class for running basic determinization algorithm on vpa.
*/
class VPADeterminizer {
public:
static label::Label packToDVPAStateLabel(const std::set<std::pair<label::Label, label::Label>>& data);
static std::set<std::pair<label::Label, label::Label>> unpackFromDVPAStateLabel(const label::Label& data);
static label::Label packToDVPAStackSymbolLabel(const std::pair<std::set<std::pair<label::Label, label::Label>>, label::Label>& data);
static std::pair<std::set<std::pair<label::Label, label::Label>>, label::Label> unpackFromDVPAStackSymbolLabel(const label::Label& data);
/**
* Runs determinization algorithm on nondeterministic vpa given in constructor.
*
* @return deterministic visibly pushdown automaton
*/
static automaton::VisiblyPushdownNPDA determinize(const automaton::VisiblyPushdownNPDA& nondeterministic);
};
} /* namespace determinize */
#endif /* VPADETERMINIZER_h_ */
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include "determinize/nfa/NFADeterminizer.h" #include "determinize/nfa/NFADeterminizer.h"
#include "determinize/idpda/IDPDADeterminizer.h" #include "determinize/idpda/IDPDADeterminizer.h"
   
#include "factory/DataFactory.hpp"
#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y)) #define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y))
   
CPPUNIT_TEST_SUITE_REGISTRATION( determinizeTest ); CPPUNIT_TEST_SUITE_REGISTRATION( determinizeTest );
...@@ -28,13 +30,13 @@ void determinizeTest::testDeterminizeNFA() { ...@@ -28,13 +30,13 @@ void determinizeTest::testDeterminizeNFA() {
automaton.addState(automaton::State(3)); automaton.addState(automaton::State(3));
automaton.addInputSymbol(alphabet::symbolFrom("a")); automaton.addInputSymbol(alphabet::symbolFrom("a"));
automaton.addInputSymbol(alphabet::symbolFrom("b")); automaton.addInputSymbol(alphabet::symbolFrom("b"));
automaton.addTransition(automaton::State(1), alphabet::symbolFrom("a"), automaton::State(2)); automaton.addTransition(automaton::State(1), alphabet::symbolFrom("a"), automaton::State(2));
automaton.addTransition(automaton::State(2), alphabet::symbolFrom("b"), automaton::State(1)); automaton.addTransition(automaton::State(2), alphabet::symbolFrom("b"), automaton::State(1));
   
automaton.addInitialState(automaton::State(1)); automaton.addInitialState(automaton::State(1));
automaton.addFinalState(automaton::State(3)); automaton.addFinalState(automaton::State(3));
automaton::DFA determinized = determinize::NFADeterminizer::determinize(automaton); automaton::DFA determinized = determinize::NFADeterminizer::determinize(automaton);
   
CPPUNIT_ASSERT(determinized.getStates().size() == 3); CPPUNIT_ASSERT(determinized.getStates().size() == 3);
...@@ -46,7 +48,7 @@ void determinizeTest::testDeterminizeIDPDA() { ...@@ -46,7 +48,7 @@ void determinizeTest::testDeterminizeIDPDA() {
   
automaton.addInputSymbol(alphabet::symbolFrom("a")); automaton.addInputSymbol(alphabet::symbolFrom("a"));
automaton.addInputSymbol(alphabet::symbolFrom("b")); automaton.addInputSymbol(alphabet::symbolFrom("b"));
automaton.setPushdownStoreOperation(alphabet::symbolFrom("a"), std::vector<alphabet::Symbol>{}, std::vector<alphabet::Symbol> {}); automaton.setPushdownStoreOperation(alphabet::symbolFrom("a"), std::vector<alphabet::Symbol>{}, std::vector<alphabet::Symbol> {});
automaton.setPushdownStoreOperation(alphabet::symbolFrom("b"), std::vector<alphabet::Symbol>{}, std::vector<alphabet::Symbol> {}); automaton.setPushdownStoreOperation(alphabet::symbolFrom("b"), std::vector<alphabet::Symbol>{}, std::vector<alphabet::Symbol> {});
   
...@@ -58,7 +60,9 @@ void determinizeTest::testDeterminizeIDPDA() { ...@@ -58,7 +60,9 @@ void determinizeTest::testDeterminizeIDPDA() {
   
automaton.addInitialState(automaton::State(1)); automaton.addInitialState(automaton::State(1));
automaton.addFinalState(automaton::State(3)); automaton.addFinalState(automaton::State(3));
alib::DataFactory::toStdout(automaton);
automaton::DPDA determinized = determinize::IDPDADeterminizer::determinize(automaton); automaton::DPDA determinized = determinize::IDPDADeterminizer::determinize(automaton);
   
CPPUNIT_ASSERT(determinized.getStates().size() == 3); CPPUNIT_ASSERT(determinized.getStates().size() == 3);
......
...@@ -48,10 +48,10 @@ Automaton AutomatonFromXMLParser::parseAutomaton(std::list<sax::Token>& input, c ...@@ -48,10 +48,10 @@ Automaton AutomatonFromXMLParser::parseAutomaton(std::list<sax::Token>& input, c
return Automaton(parseSinglePopDPDA(input)); return Automaton(parseSinglePopDPDA(input));
} else if(isToken(input, sax::Token::TokenType::START_ELEMENT, "InputDrivenNPDA")) { } else if(isToken(input, sax::Token::TokenType::START_ELEMENT, "InputDrivenNPDA")) {
if(!features.count(FEATURES::INPUT_DRIVEN_NPDA)) throw exception::AlibException(); if(!features.count(FEATURES::INPUT_DRIVEN_NPDA)) throw exception::AlibException();
return Automaton(parseNPDA(input)); return Automaton(parseInputDrivenNPDA(input));
} else if(isToken(input, sax::Token::TokenType::START_ELEMENT, "VisiblyPushdownNPDA")) { } else if(isToken(input, sax::Token::TokenType::START_ELEMENT, "VisiblyPushdownNPDA")) {
if(!features.count(FEATURES::VISIBLY_PUSHDOWN_NPDA)) throw exception::AlibException(); if(!features.count(FEATURES::VISIBLY_PUSHDOWN_NPDA)) throw exception::AlibException();
return Automaton(parseSinglePopNPDA(input)); return Automaton(parseVisiblyPushdownNPDA(input));
} else if(isToken(input, sax::Token::TokenType::START_ELEMENT, "NPDA")) { } else if(isToken(input, sax::Token::TokenType::START_ELEMENT, "NPDA")) {
if(!features.count(FEATURES::NPDA)) throw exception::AlibException(); if(!features.count(FEATURES::NPDA)) throw exception::AlibException();
return Automaton(parseNPDA(input)); return Automaton(parseNPDA(input));
...@@ -66,7 +66,7 @@ Automaton AutomatonFromXMLParser::parseAutomaton(std::list<sax::Token>& input, c ...@@ -66,7 +66,7 @@ Automaton AutomatonFromXMLParser::parseAutomaton(std::list<sax::Token>& input, c
} }
   
bool AutomatonFromXMLParser::first(std::list<sax::Token>& input) const { bool AutomatonFromXMLParser::first(std::list<sax::Token>& input) const {
if(isToken(input, sax::Token::TokenType::START_ELEMENT, "automaton") || isToken(input, sax::Token::TokenType::START_ELEMENT, "EpsilonNFA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "NFA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "DFA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "CompactNFA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "ExtendedNFA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "DPDA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "SinglePopDPDA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "NPDA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "SinglePopNPDA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "OneTapeDTM")) { if(isToken(input, sax::Token::TokenType::START_ELEMENT, "automaton") || isToken(input, sax::Token::TokenType::START_ELEMENT, "EpsilonNFA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "NFA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "DFA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "CompactNFA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "ExtendedNFA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "DPDA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "SinglePopDPDA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "InputDrivenNPDA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "VisiblyPushdownNPDA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "NPDA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "SinglePopNPDA") || isToken(input, sax::Token::TokenType::START_ELEMENT, "OneTapeDTM")) {
return true; return true;
} else { } else {
return false; return false;
...@@ -532,7 +532,7 @@ void AutomatonFromXMLParser::parseInputToPushdownStoreOperation(std::list<sax::T ...@@ -532,7 +532,7 @@ void AutomatonFromXMLParser::parseInputToPushdownStoreOperation(std::list<sax::T
while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) { while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
popToken(input, sax::Token::TokenType::START_ELEMENT, "operation"); popToken(input, sax::Token::TokenType::START_ELEMENT, "operation");
   
alphabet::Symbol inputSymbol = parseTransitionInputSymbol(input); alphabet::Symbol inputSymbol(alib::api<alphabet::Symbol>::parse(input));
   
std::vector<alphabet::Symbol> pop = parseTransitionPop(input); std::vector<alphabet::Symbol> pop = parseTransitionPop(input);
std::vector<alphabet::Symbol> push = parseTransitionPush(input); std::vector<alphabet::Symbol> push = parseTransitionPush(input);
......
...@@ -118,7 +118,7 @@ void AutomatonToXMLComposer::composeBottomOfTheStackSymbol(std::list<sax::Token> ...@@ -118,7 +118,7 @@ void AutomatonToXMLComposer::composeBottomOfTheStackSymbol(std::list<sax::Token>
   
void AutomatonToXMLComposer::composeInputToPushdownStoreOperation(std::list<sax::Token>& out, const automaton::InputDrivenNPDA& automaton) const { void AutomatonToXMLComposer::composeInputToPushdownStoreOperation(std::list<sax::Token>& out, const automaton::InputDrivenNPDA& automaton) const {
out.push_back(sax::Token("inputToPushdownStoreOperation", sax::Token::TokenType::START_ELEMENT)); out.push_back(sax::Token("inputToPushdownStoreOperations", sax::Token::TokenType::START_ELEMENT));
for(const auto& pushdownStoreOperation : automaton.getPushdownStoreOperations()) { for(const auto& pushdownStoreOperation : automaton.getPushdownStoreOperations()) {
out.push_back(sax::Token("operation", sax::Token::TokenType::START_ELEMENT)); out.push_back(sax::Token("operation", sax::Token::TokenType::START_ELEMENT));
...@@ -129,7 +129,7 @@ void AutomatonToXMLComposer::composeInputToPushdownStoreOperation(std::list<sax: ...@@ -129,7 +129,7 @@ void AutomatonToXMLComposer::composeInputToPushdownStoreOperation(std::list<sax:
   
out.push_back(sax::Token("operation", sax::Token::TokenType::END_ELEMENT)); out.push_back(sax::Token("operation", sax::Token::TokenType::END_ELEMENT));
} }
out.push_back(sax::Token("inputToPushdownStoreOperation", sax::Token::TokenType::END_ELEMENT)); out.push_back(sax::Token("inputToPushdownStoreOperations", sax::Token::TokenType::END_ELEMENT));
} }
   
void AutomatonToXMLComposer::composeTransitions(std::list<sax::Token>& out, const UnknownAutomaton& automaton) const { void AutomatonToXMLComposer::composeTransitions(std::list<sax::Token>& out, const UnknownAutomaton& automaton) const {
...@@ -644,8 +644,8 @@ std::list<sax::Token> AutomatonToXMLComposer::compose(const InputDrivenNPDA& aut ...@@ -644,8 +644,8 @@ std::list<sax::Token> AutomatonToXMLComposer::compose(const InputDrivenNPDA& aut
composeInputAlphabet(out, automaton.getInputAlphabet()); composeInputAlphabet(out, automaton.getInputAlphabet());
composeStackAlphabet(out, automaton.getStackAlphabet()); composeStackAlphabet(out, automaton.getStackAlphabet());
composeInitialStates(out, automaton.getInitialStates()); composeInitialStates(out, automaton.getInitialStates());
composeFinalStates(out, automaton.getFinalStates());
composeInitialStackSymbol(out, automaton.getInitialSymbol()); composeInitialStackSymbol(out, automaton.getInitialSymbol());
composeFinalStates(out, automaton.getFinalStates());
composeInputToPushdownStoreOperation(out, automaton); composeInputToPushdownStoreOperation(out, automaton);
composeTransitions(out, automaton); composeTransitions(out, automaton);
   
......
<InputDrivenNPDA>
<states>
<IntegerLabel>1</IntegerLabel>
<IntegerLabel>2</IntegerLabel>
<IntegerLabel>3</IntegerLabel>
</states>
<inputAlphabet>
<LabeledSymbol>
<StringLabel>a</StringLabel>
</LabeledSymbol>
<LabeledSymbol>
<StringLabel>b</StringLabel>
</LabeledSymbol>
</inputAlphabet>
<stackAlphabet>
<LabeledSymbol>
<CharacterLabel>S</CharacterLabel>
</LabeledSymbol>
</stackAlphabet>
<initialStates>
<IntegerLabel>1</IntegerLabel>
</initialStates>
<initialStackSymbol>
<LabeledSymbol>
<CharacterLabel>S</CharacterLabel>
</LabeledSymbol>
</initialStackSymbol>
<finalStates>
<IntegerLabel>3</IntegerLabel>
</finalStates>
<inputToPushdownStoreOperations>
<operation>
<LabeledSymbol>
<StringLabel>a</StringLabel>
</LabeledSymbol>
<pop/>
<push/>
</operation>
<operation>
<LabeledSymbol>
<StringLabel>b</StringLabel>
</LabeledSymbol>
<pop/>
<push/>
</operation>
</inputToPushdownStoreOperations>
<transitions>
<transition>
<from>
<IntegerLabel>1</IntegerLabel>
</from>
<input>
<LabeledSymbol>
<StringLabel>a</StringLabel>
</LabeledSymbol>
</input>
<to>
<IntegerLabel>2</IntegerLabel>
</to>
</transition>
<transition>
<from>
<IntegerLabel>2</IntegerLabel>
</from>
<input>
<LabeledSymbol>
<StringLabel>b</StringLabel>
</LabeledSymbol>
</input>
<to>
<IntegerLabel>1</IntegerLabel>
</to>
</transition>
<transition>
<from>
<IntegerLabel>2</IntegerLabel>
</from>
<input>
<LabeledSymbol>
<StringLabel>b</StringLabel>
</LabeledSymbol>
</input>
<to>
<IntegerLabel>3</IntegerLabel>
</to>
</transition>
</transitions>
</InputDrivenNPDA>
<InputDrivenNPDA>
<states>
<IntegerLabel>0</IntegerLabel>
<IntegerLabel>1</IntegerLabel>
<IntegerLabel>2</IntegerLabel>
<IntegerLabel>3</IntegerLabel>
</states>
<inputAlphabet>
<LabeledSymbol>
<StringLabel>a</StringLabel>
</LabeledSymbol>
<LabeledSymbol>
<StringLabel>b</StringLabel>
</LabeledSymbol>
<LabeledSymbol>
<StringLabel>c</StringLabel>
</LabeledSymbol>
<LabeledSymbol>
<StringLabel>d</StringLabel>
</LabeledSymbol>
</inputAlphabet>
<stackAlphabet>
<LabeledSymbol>
<StringLabel>a</StringLabel>
</LabeledSymbol>
<LabeledSymbol>
<StringLabel>b</StringLabel>
</LabeledSymbol>
</stackAlphabet>
<initialStates>
<IntegerLabel>0</IntegerLabel>
</initialStates>
<initialStackSymbol>
<LabeledSymbol>
<StringLabel>a</StringLabel>
</LabeledSymbol>
</initialStackSymbol>
<finalStates>
<IntegerLabel>3</IntegerLabel>
</finalStates>
<inputToPushdownStoreOperations>
<operation>
<LabeledSymbol>
<StringLabel>a</StringLabel>
</LabeledSymbol>
<pop/>
<push>
<LabeledSymbol>
<StringLabel>a</StringLabel>
</LabeledSymbol>
</push>
</operation>
<operation>
<LabeledSymbol>
<StringLabel>b</StringLabel>
</LabeledSymbol>
<pop/>
<push>
<LabeledSymbol>
<StringLabel>b</StringLabel>
</LabeledSymbol>
</push>
</operation>
<operation>
<LabeledSymbol>
<StringLabel>c</StringLabel>
</LabeledSymbol>
<pop>
<LabeledSymbol>
<StringLabel>b</StringLabel>
</LabeledSymbol>
</pop>
<push/>
</operation>
<operation>
<LabeledSymbol>
<StringLabel>d</StringLabel>
</LabeledSymbol>
<pop>
<LabeledSymbol>
<StringLabel>a</StringLabel>
</LabeledSymbol>
</pop>
<push/>
</operation>
</inputToPushdownStoreOperations>
<transitions>
<transition>
<from>
<IntegerLabel>0</IntegerLabel>
</from>
<input>
<LabeledSymbol>
<StringLabel>a</StringLabel>
</LabeledSymbol>
</input>
<to>
<IntegerLabel>1</IntegerLabel>
</to>
</transition>
<transition>
<from>
<IntegerLabel>1</IntegerLabel>
</from>
<input>
<LabeledSymbol>
<StringLabel>b</StringLabel>
</LabeledSymbol>
</input>
<to>
<IntegerLabel>1</IntegerLabel>
</to>
</transition>
<transition>
<from>
<IntegerLabel>1</IntegerLabel>
</from>
<input>
<LabeledSymbol>
<StringLabel>b</StringLabel>
</LabeledSymbol>
</input>
<to>
<IntegerLabel>2</IntegerLabel>
</to>
</transition>
<transition>
<from>
<IntegerLabel>2</IntegerLabel>
</from>
<input>
<LabeledSymbol>
<StringLabel>c</StringLabel>
</LabeledSymbol>
</input>
<to>
<IntegerLabel>2</IntegerLabel>
</to>
</transition>
<transition>
<from>
<IntegerLabel>2</IntegerLabel>
</from>
<input>
<LabeledSymbol>
<StringLabel>d</StringLabel>
</LabeledSymbol>
</input>
<to>
<IntegerLabel>3</IntegerLabel>
</to>
</transition>
</transitions>
</InputDrivenNPDA>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment