/*
 * VisiblyPushdownDPDA.h
 *
 * This file is part of Algorithms library toolkit.
 * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz)

 * Algorithms library toolkit 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 3 of the License, or
 * (at your option) any later version.

 * Algorithms library toolkit 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 Algorithms library toolkit.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  Created on: Mar 25, 2013
 *      Author: Jan Travnicek
 */

#ifndef VISIBLY_PUSHDOWN_DPDA_H_
#define VISIBLY_PUSHDOWN_DPDA_H_

#include <sstream>

#include <alib/map>
#include <alib/set>
#include <alib/vector>
#include <alib/algorithm>
#include <alib/compare>

#include <core/components.hpp>

#include <common/DefaultStateType.h>
#include <common/DefaultSymbolType.h>

#include <automaton/AutomatonException.h>

#include <core/normalize.hpp>
#include <alphabet/common/SymbolNormalize.h>
#include <automaton/common/AutomatonNormalize.h>

namespace automaton {

class CallAlphabet;
class ReturnAlphabet;
class LocalAlphabet;
class PushdownStoreAlphabet;
class BottomOfTheStackSymbol;
class States;
class FinalStates;
class InitialState;

/**
 * \brief
 * Deterministic visibly pushdown automaton. Accepts subset of context free languages.

 * \details
 * Definition
 * A = (Q, T = C \cup R \cup L, G, I, Z, \delta, F),
 * Q (States) = nonempty finite set of states,
 * T (TerminalAlphabet) = finite set of terminal symbols split to three disjoint parts
 *   - C (CallAlphabet) = symbols used with transitions increasing the pushdown store,
 *   - R (ReturnAlphabet) = symbols used with transitions decreasing the pushdown store,
 *   - L (LocalAlphabet) = symbols used with transitions leaving the height of the pushdown store unchanged
 * G (PushdownStoreAlphabet) = finite set of pushdown store symbol - having this empty makes the automaton equivalent to DFA
 * I (InitialState) = initial state,
 * Z (BottomOfTheStackSymbol) = initial pushdown store symbol
 * \delta is split to three disjoint parts
 *   - \delta_{call} of the form A \times c -> B \times g, where A, B \in Q, a \in C, and g \in G
 *   - \delta_{return} of the form A \times r \times g -> B, where A, B \in Q, r \in C, and g \in G
 *   - \delta_{local} of the form A \times l -> B, where A, B \in Q, a \in C
 * F (FinalStates) = set of final states
 *
 * The transition functions must meet following criteria. Othervise adding conflicting transition will cause exception.
 * $|\delta_{call} (q, c)| \leq 1$, $\forall q \in Q, c \in C$
 * $|\delta_{return} (q, r, g)| \leq 1$, $\forall q \in Q, r \in L, g \in G$
 * $|\delta_{local} (q, l)| \leq 1$, $\forall q \in Q, l \in R$
 *
 * \tparam InputSymbolTypeT used for the terminal alphabet
 * \tparam PushdownSymbolTypeT used for the pushdown store alphabet
 * \tparam StateTypeT used to the states, and the initial state of the automaton.
 */
template < class InputSymbolTypeT = DefaultSymbolType, class PushdownStoreSymbolTypeT = DefaultSymbolType, class StateTypeT = DefaultStateType >
class VisiblyPushdownDPDA final : public ext::CompareOperators < VisiblyPushdownDPDA < InputSymbolTypeT, PushdownStoreSymbolTypeT, StateTypeT > >, public core::Components < VisiblyPushdownDPDA < InputSymbolTypeT, PushdownStoreSymbolTypeT, StateTypeT >, ext::set < InputSymbolTypeT >, component::Set, std::tuple < CallAlphabet, ReturnAlphabet, LocalAlphabet >, ext::set < PushdownStoreSymbolTypeT >, component::Set, PushdownStoreAlphabet, PushdownStoreSymbolTypeT, component::Value, BottomOfTheStackSymbol, ext::set < StateTypeT >, component::Set, std::tuple < States, FinalStates >, StateTypeT, component::Value, InitialState > {
public:
	typedef InputSymbolTypeT InputSymbolType;
	typedef PushdownStoreSymbolTypeT PushdownStoreSymbolType;
	typedef StateTypeT StateType;

private:
	/**
	 * Call transition function as mapping from a state times an input symbol on the left hand side to a state times pushdown store symbol on the right hand side.
	 */
	ext::map < ext::pair < StateType, InputSymbolType >, ext::pair < StateType, PushdownStoreSymbolType > > callTransitions;

	/**
	 * Return transition function as mapping from a state times an input symbol times pushdown store symbol on the left hand side to a state on the right hand side.
	 */
	ext::map < ext::tuple < StateType, InputSymbolType, PushdownStoreSymbolType >, StateType > returnTransitions;

	/**
	 * Local transition function as mapping from a state times an input symbol on the left hand side to a state on the right hand side.
	 */
	ext::map < ext::pair < StateType, InputSymbolType >, StateType > localTransitions;

public:
	/**
	 * StateType template param
	 */
	using StateType_t = StateType;

	/**
	 * PushdownStoreSymbolType template param
	 */
	using PushdownStoreSymbolType_t = PushdownStoreSymbolType;

	/**
	 * \brief Creates a new instance of the automaton with a concrete set of states, call, return, and local alphabets, pushdown store alphabet, initial state, bottom of the stack symbol, and a set of final states.
	 *
	 * \param states the initial set of states of the automaton
	 * \param callAlphabet the initial input alphabet
	 * \param returnAlphabet the initial input alphabet
	 * \param localAlphabet the initial input alphabet
	 * \param pushdownStoreAlphabet the initial set of symbols used in the pushdown store by the automaton
	 * \param initialState the initial state of the automaton
	 * \param bottomOfTheStackSymbol the initial pushdown symbol of the automaton
	 * \param finalStates the initial set of final states of the automaton
	 */
	explicit VisiblyPushdownDPDA ( ext::set < StateType > states, ext::set < InputSymbolType > callAlphabet, ext::set < InputSymbolType > returnAlphabet, ext::set < InputSymbolType > localAlphabet, ext::set < PushdownStoreSymbolType > pushdownStoreAlphabet, StateType initialState, PushdownStoreSymbolType bottomOfTheStackSymbol, ext::set < StateType > finalStates );

	/**
	 * \brief Creates a new instance of the automaton with a concrete initial state and bottom of the stack symbol.
	 *
	 * \param initialState the initial state of the automaton
	 * \param bottomOfTheStackSymbol the bottom of the stack symbol of the automaton
	 */
	explicit VisiblyPushdownDPDA ( StateType initialState, PushdownStoreSymbolType bottomOfTheStackSymbol );

	/**
	 * Getter of the initial state.
	 *
	 * \returns the initial state of the automaton
	 */
	const StateType & getInitialState ( ) const & {
		return this-> template accessComponent < InitialState > ( ).get ( );
	}

	/**
	 * Getter of the initial state.
	 *
	 * \returns the initial state of the automaton
	 */
	StateType && getInitialState ( ) && {
		return std::move ( this-> template accessComponent < InitialState > ( ).get ( ) );
	}

	/**
	 * Setter of the initial state.
	 *
	 * \param state new initial state of the automaton
	 *
	 * \returns true if the initial state was indeed changed
	 */
	bool setInitialState ( StateType state ) {
		return this-> template accessComponent < InitialState > ( ).set ( std::move ( state ) );
	}

	/**
	 * Getter of states.
	 *
	 * \returns the states of the automaton
	 */
	const ext::set < StateType > & getStates ( ) const & {
		return this-> template accessComponent < States > ( ).get ( );
	}

	/**
	 * Getter of states.
	 *
	 * \returns the states of the automaton
	 */
	ext::set < StateType > && getStates ( ) && {
		return std::move ( this-> template accessComponent < States > ( ).get ( ) );
	}

	/**
	 * Adder of a state.
	 *
	 * \param state the new state to be added to a set of states
	 *
	 * \returns true if the state was indeed added
	 */
	bool addState ( StateType state ) {
		return this-> template accessComponent < States > ( ).add ( std::move ( state ) );
	}

	/**
	 * Setter of states.
	 *
	 * \param states completely new set of states
	 */
	void setStates ( ext::set < StateType > states ) {
		this-> template accessComponent < States > ( ).set ( std::move ( states ) );
	}

	/**
	 * Remover of a state.
	 *
	 * \param state a state to be removed from a set of states
	 *
	 * \returns true if the state was indeed removed
	 */
	bool removeState ( const StateType & state ) {
		return this-> template accessComponent < States > ( ).remove ( state );
	}

	/**
	 * Getter of final states.
	 *
	 * \returns the final states of the automaton
	 */
	const ext::set < StateType > & getFinalStates ( ) const & {
		return this-> template accessComponent < FinalStates > ( ).get ( );
	}

	/**
	 * Getter of final states.
	 *
	 * \returns the final states of the automaton
	 */
	ext::set < StateType > && getFinalStates ( ) && {
		return std::move ( this-> template accessComponent < FinalStates > ( ).get ( ) );
	}

	/**
	 * Adder of a final state.
	 *
	 * \param state the new state to be added to a set of final states
	 *
	 * \returns true if the state was indeed added
	 */
	bool addFinalState ( StateType state ) {
		return this-> template accessComponent < FinalStates > ( ).add ( std::move ( state ) );
	}

	/**
	 * Setter of final states.
	 *
	 * \param states completely new set of final states
	 */
	void setFinalStates ( ext::set < StateType > states ) {
		this-> template accessComponent < FinalStates > ( ).set ( std::move ( states ) );
	}

	/**
	 * Remover of a final state.
	 *
	 * \param state a state to be removed from a set of final states
	 *
	 * \returns true if the state was indeed removed
	 */
	bool removeFinalState ( const StateType & state ) {
		return this-> template accessComponent < FinalStates > ( ).remove ( state );
	}

	/**
	 * Getter of the pushdown store alphabet.
	 *
	 * \returns the pushdown store alphabet of the automaton
	 */
	const ext::set < PushdownStoreSymbolType > & getPushdownStoreAlphabet ( ) const & {
		return this->template accessComponent < PushdownStoreAlphabet > ( ).get ( );
	}

	/**
	 * Getter of the pushdown store alphabet.
	 *
	 * \returns the pushdown store alphabet of the automaton
	 */
	ext::set < PushdownStoreSymbolType > && getPushdownStoreAlphabet ( ) && {
		return std::move ( this->template accessComponent < PushdownStoreAlphabet > ( ).get ( ) );
	}

	/**
	 * Adder of a pushdown store symbol.
	 *
	 * \param symbol the new symbol to be added to a pushdown store alphabet
	 *
	 * \returns true if the symbol was indeed added
	 */
	bool addPushdownStoreSymbol ( PushdownStoreSymbolType symbol ) {
		return this->template accessComponent < PushdownStoreAlphabet > ( ).add ( std::move ( symbol ) );
	}

	/**
	 * Adder of pushdown store symbols.
	 *
	 * \param symbols new symbols to be added to a pushdown store alphabet
	 */
	void addPushdownStoreSymbols ( ext::set < PushdownStoreSymbolType > symbols ) {
		this->template accessComponent < PushdownStoreAlphabet > ( ).add ( std::move ( symbols ) );
	}

	/**
	 * Setter of a pushdown store alphabet.
	 *
	 * \param symbols completely new pushdown store alphabet
	 */
	void setPushdownStoreAlphabet ( ext::set < PushdownStoreSymbolType > symbols ) {
		this->template accessComponent < PushdownStoreAlphabet > ( ).set ( std::move ( symbols ) );
	}

	/**
	 * Remover of an pushdown store symbol.
	 *
	 * \param symbol a symbol to be removed from a pushdown store alphabet
	 *
	 * \returns true if the symbol was indeed removed
	 */
	bool removePushdownStoreSymbol ( const PushdownStoreSymbolType & symbol ) {
		return this->template accessComponent < PushdownStoreAlphabet > ( ).remove ( symbol );
	}

	/**
	 * Getter of the bottom of the stack symbol.
	 *
	 * \returns the bottom of the stack symbol of the automaton
	 */
	const PushdownStoreSymbolType & getBottomOfTheStackSymbol ( ) const & {
		return this->template accessComponent < BottomOfTheStackSymbol > ( ).get ( );
	}

	/**
	 * Getter of the bottom of the stack symbol.
	 *
	 * \returns the bottom of the stack symbol of the automaton
	 */
	PushdownStoreSymbolType && getBottomOfTheStackSymbol ( ) && {
		return std::move ( this->template accessComponent < BottomOfTheStackSymbol > ( ).get ( ) );
	}

	/**
	 * Setter of the bottom of the stack symbol.
	 *
	 * \param symbol new bottom of the stack symbol of the automaton
	 *
	 * \returns true if the bottom of the stack symbol was indeed changed
	 */
	bool setBottomOfTheStackSymbol ( PushdownStoreSymbolType symbol ) {
		return this->template accessComponent < BottomOfTheStackSymbol > ( ).set ( std::move ( symbol ) );
	}

	/**
	 * Getter of the call part of the input alphabet.
	 *
	 * \returns the call part of the input alphabet of the automaton
	 */
	const ext::set < InputSymbolType > & getCallInputAlphabet ( ) const & {
		return this->template accessComponent < CallAlphabet > ( ).get ( );
	}

	/**
	 * Getter of the call part of the input alphabet.
	 *
	 * \returns the the call part of the input alphabet of the automaton
	 */
	ext::set < InputSymbolType > && getCallInputAlphabet ( ) && {
		return std::move ( this->template accessComponent < CallAlphabet > ( ).get ( ) );
	}

	/**
	 * Adder of a symbol to call part of the input alphabet.
	 *
	 * \param symbol the new symbol to be added to a call part of the input alphabet
	 *
	 * \returns true if the symbol was indeed added
	 */
	bool addCallInputSymbol ( InputSymbolType symbol ) {
		return this->template accessComponent < CallAlphabet > ( ).add ( std::move ( symbol ) );
	}

	/**
	 * Adder of a symbol to a call part of the input alphabet.
	 *
	 * \param symbols new symbols to be added to a call part of the input alphabet
	 */
	void addCallInputSymbols ( ext::set < InputSymbolType > symbols ) {
		this->template accessComponent < CallAlphabet > ( ).add ( std::move ( symbols ) );
	}

	/**
	 * Setter of a call part of the input alphabet.
	 *
	 * \param symbols completely new call part of the input alphabet
	 */
	void setCallInputAlphabet ( ext::set < InputSymbolType > symbols ) {
		this->template accessComponent < CallAlphabet > ( ).set ( std::move ( symbols ) );
	}

	/**
	 * Remover of a call input symbol.
	 *
	 * \param symbol a symbol to be removed from a call part of the input alphabet
	 *
	 * \returns true if the symbol was indeed removed
	 */
	bool removeCallInputSymbol ( const InputSymbolType & symbol ) {
		return this->template accessComponent < CallAlphabet > ( ).remove ( symbol );
	}

	/**
	 * Getter of the call part of the input alphabet.
	 *
	 * \returns the call part of the input alphabet of the automaton
	 */
	const ext::set < InputSymbolType > & getReturnInputAlphabet ( ) const & {
		return this->template accessComponent < ReturnAlphabet > ( ).get ( );
	}

	/**
	 * Getter of the call part of the input alphabet.
	 *
	 * \returns the the call part of the input alphabet of the automaton
	 */
	ext::set < InputSymbolType > && getReturnInputAlphabet ( ) && {
		return std::move ( this->template accessComponent < ReturnAlphabet > ( ).get ( ) );
	}

	/**
	 * Adder of a symbol to call part of the input alphabet.
	 *
	 * \param symbol the new symbol to be added to a call part of the input alphabet
	 *
	 * \returns true if the symbol was indeed added
	 */
	bool addReturnInputSymbol ( InputSymbolType symbol ) {
		return this->template accessComponent < ReturnAlphabet > ( ).add ( std::move ( symbol ) );
	}

	/**
	 * Adder of a symbol to a call part of the input alphabet.
	 *
	 * \param symbols new symbols to be added to a call part of the input alphabet
	 */
	void addReturnInputSymbols ( ext::set < InputSymbolType > symbols ) {
		this->template accessComponent < ReturnAlphabet > ( ).add ( std::move ( symbols ) );
	}

	/**
	 * Setter of a call part of the input alphabet.
	 *
	 * \param symbols completely new call part of the input alphabet
	 */
	void setReturnInputAlphabet ( ext::set < InputSymbolType > symbols ) {
		this->template accessComponent < ReturnAlphabet > ( ).set ( std::move ( symbols ) );
	}

	/**
	 * Remover of a call input symbol.
	 *
	 * \param symbol a symbol to be removed from a call part of the input alphabet
	 *
	 * \returns true if the symbol was indeed removed
	 */
	bool removeReturnInputSymbol ( const InputSymbolType & symbol ) {
		return this->template accessComponent < ReturnAlphabet > ( ).remove ( symbol );
	}

	/**
	 * Getter of the call part of the input alphabet.
	 *
	 * \returns the call part of the input alphabet of the automaton
	 */
	const ext::set < InputSymbolType > & getLocalInputAlphabet ( ) const & {
		return this->template accessComponent < LocalAlphabet > ( ).get ( );
	}

	/**
	 * Getter of the call part of the input alphabet.
	 *
	 * \returns the the call part of the input alphabet of the automaton
	 */
	ext::set < InputSymbolType > && getLocalInputAlphabet ( ) && {
		return std::move ( this->template accessComponent < LocalAlphabet > ( ).get ( ) );
	}

	/**
	 * Adder of a symbol to call part of the input alphabet.
	 *
	 * \param symbol the new symbol to be added to a call part of the input alphabet
	 *
	 * \returns true if the symbol was indeed added
	 */
	bool addLocalInputSymbol ( InputSymbolType symbol ) {
		return this->template accessComponent < LocalAlphabet > ( ).add ( std::move ( symbol ) );
	}

	/**
	 * Adder of a symbol to a call part of the input alphabet.
	 *
	 * \param symbols new symbols to be added to a call part of the input alphabet
	 */
	void addLocalInputSymbols ( ext::set < InputSymbolType > symbols ) {
		this->template accessComponent < LocalAlphabet > ( ).add ( std::move ( symbols ) );
	}

	/**
	 * Setter of a call part of the input alphabet.
	 *
	 * \param symbols completely new call part of the input alphabet
	 */
	void setLocalInputAlphabet ( ext::set < InputSymbolType > symbols ) {
		this->template accessComponent < LocalAlphabet > ( ).set ( std::move ( symbols ) );
	}

	/**
	 * Remover of a call input symbol.
	 *
	 * \param symbol a symbol to be removed from a call part of the input alphabet
	 *
	 * \returns true if the symbol was indeed removed
	 */
	bool removeLocalInputSymbol ( const InputSymbolType & symbol ) {
		return this->template accessComponent < LocalAlphabet > ( ).remove ( symbol );
	}

	/**
	 * Remover of a input symbol.
	 *
	 * \param symbol a symbol to be removed from the input alphabet
	 *
	 * \returns true if the symbol was indeed removed
	 */
	bool removeInputSymbol(const InputSymbolType& symbol) {
		return removeCallInputSymbol(symbol) || removeReturnInputSymbol(symbol) || removeLocalInputSymbol(symbol);
	}

	/**
	 * \brief Adds a call transition to the automaton.
	 *
	 * \details The transition is in a form A \times a -> B \times g, where A, B \in Q, a \in C, and g \in G
	 *
	 * \param from the source state (A)
	 * \param input the call input symbol (a)
	 * \param to the target state (B)
	 * \param push symbol to be pushed to the pushdown store on the transition use (g)
	 *
	 * \throws AutomatonException when transition contains state or symbol not present in the automaton components or when the transition would cause nondeterminism
	 *
	 * \returns true if the transition was indeed added
	 */
	bool addCallTransition ( StateType from, InputSymbolType input, StateType to, PushdownStoreSymbolType push );

	/**
	 * \brief Adds a return transition to the automaton.
	 *
	 * \details The transition is in a form A \times a \times g -> B, where A, B \in Q, a \in C, and g \in G
	 *
	 * \param from the source state (A)
	 * \param input the return input symbol (a)
	 * \param pop symbol to be poped to the pushdown store on the transition use (g)
	 * \param to the target state (B)
	 *
	 * \throws AutomatonException when transition contains state or symbol not present in the automaton components or when the transition would cause nondeterminism
	 *
	 * \returns true if the transition was indeed added
	 */
	bool addReturnTransition ( StateType from, InputSymbolType input, PushdownStoreSymbolType pop, StateType to );

	/**
	 * \brief Adds a local transition to the automaton.
	 *
	 * \details The transition is in a form A \times a -> B, where A, B \in Q and a \in C
	 *
	 * \param from the source state (A)
	 * \param input the local input symbol (a)
	 * \param to the target state (B)
	 *
	 * \throws AutomatonException when transition contains state or symbol not present in the automaton components or when the transition would cause nondeterminism
	 *
	 * \returns true if the transition was indeed added
	 */
	bool addLocalTransition ( StateType from, InputSymbolType input, StateType to );

	/**
	 * \brief Removes a call transition from the automaton.
	 *
	 * \details The transition is in a form A \times a -> B \times g, where A, B \in Q, a \in C, and g \in G
	 *
	 * \param from the source state (A)
	 * \param input the call input symbol (a)
	 * \param to the target state (B)
	 * \param push symbol to be pushed to the pushdown store on the transition use (g)
	 *
	 * \throws AutomatonException when removed transition left hand side was found but the right hand side did not match.
	 *
	 * \returns true if the transition was indeed removed
	 */
	bool removeCallTransition ( const StateType & from, const InputSymbolType & input, const StateType & to, const PushdownStoreSymbolType & push );

	/**
	 * \brief Removes a return transition from the automaton.
	 *
	 * \details The transition is in a form A \times a \times g -> B, where A, B \in Q, a \in C, and g \in G
	 *
	 * \param from the source state (A)
	 * \param input the return input symbol (a)
	 * \param pop symbol to be poped to the pushdown store on the transition use (g)
	 * \param to the target state (B)
	 *
	 * \throws AutomatonException when removed transition left hand side was found but the right hand side did not match.
	 *
	 * \returns true if the transition was indeed removed
	 */
	bool removeReturnTransition ( const StateType & from, const InputSymbolType & input, const PushdownStoreSymbolType & pop, const StateType & to );

	/**
	 * \brief Removes a local transition from the automaton.
	 *
	 * \details The transition is in a form A \times a -> B, where A, B \in Q and a \in C
	 *
	 * \param from the source state (A)
	 * \param input the local input symbol (a)
	 * \param to the target state (B)
	 *
	 * \throws AutomatonException when removed transition left hand side was found but the right hand side did not match.
	 *
	 * \returns true if the transition was indeed removed
	 */
	bool removeLocalTransition ( const StateType & from, const InputSymbolType & input, const StateType & to );

	/**
	 * Get the call transition function of the automaton in its natural form.
	 *
	 * \returns call transition function of the automaton
	 */
	const ext::map < ext::pair < StateType, InputSymbolType >, ext::pair < StateType, PushdownStoreSymbolType > > & getCallTransitions ( ) const &;

	/**
	 * Get the call transition function of the automaton in its natural form.
	 *
	 * \returns call transition function of the automaton
	 */
	ext::map < ext::pair < StateType, InputSymbolType >, ext::pair < StateType, PushdownStoreSymbolType > > && getCallTransitions ( ) &&;

	/**
	 * Get the return transition function of the automaton in its natural form.
	 *
	 * \returns return transition function of the automaton
	 */
	const ext::map < ext::tuple < StateType, InputSymbolType, PushdownStoreSymbolType >, StateType > & getReturnTransitions ( ) const &;

	/**
	 * Get the return transition function of the automaton in its natural form.
	 *
	 * \returns return transition function of the automaton
	 */
	ext::map < ext::tuple < StateType, InputSymbolType, PushdownStoreSymbolType >, StateType > && getReturnTransitions ( ) &&;

	/**
	 * Get the local transition function of the automaton in its natural form.
	 *
	 * \returns local transition function of the automaton
	 */
	const ext::map < ext::pair < StateType, InputSymbolType >, StateType > & getLocalTransitions ( ) const &;

	/**
	 * Get the local transition function of the automaton in its natural form.
	 *
	 * \returns local transition function of the automaton
	 */
	ext::map < ext::pair < StateType, InputSymbolType >, StateType > && getLocalTransitions ( ) &&;

	/**
	 * The actual compare method
	 *
	 * \param other the other instance
	 *
	 * \returns the actual relation between two by type same automata instances
	 */
	int compare ( const VisiblyPushdownDPDA & other ) const;

	/**
	 * Print this object as raw representation to ostream.
	 *
	 * \param out ostream where to print
	 * \param instance object to print
	 *
	 * \returns modified output stream
	 */
	friend std::ostream & operator << ( std::ostream & out, const VisiblyPushdownDPDA & instance ) {
		return out << "(VisiblyPushdownDPDA "
			   << "states = " << instance.getStates ( )
			   << "callAlphabet = " << instance.getCallInputAlphabet ( )
			   << "returnAlphabet = " << instance.getReturnInputAlphabet ( )
			   << "localAlphabet = " << instance.getLocalInputAlphabet ( )
			   << "initialState = " << instance.getInitialState ( )
			   << "finalStates = " << instance.getFinalStates ( )
			   << "pushdownStoreAlphabet = " << instance.getPushdownStoreAlphabet ( )
			   << "bottomOfTheStackSymbol = " << instance.getBottomOfTheStackSymbol ( )
			   << "callTransitions = " << instance.getCallTransitions ( )
			   << "returnTransitions = " << instance.getReturnTransitions ( )
			   << "localTransitions = " << instance.getLocalTransitions ( )
			   << ")";
	}

	/**
	 * Casts this instance to as compact as possible string representation.
	 *
	 * \returns string representation of the object
	 */
	explicit operator std::string ( ) const;
};

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::VisiblyPushdownDPDA ( ext::set < StateType > states, ext::set < InputSymbolType > callAlphabet, ext::set < InputSymbolType > returnAlphabet, ext::set < InputSymbolType > localAlphabet, ext::set < PushdownStoreSymbolType > pushdownStoreAlphabet, StateType initialState, PushdownStoreSymbolType bottomOfTheStackSymbol, ext::set < StateType > finalStates ) : core::Components < VisiblyPushdownDPDA, ext::set < InputSymbolType >, component::Set, std::tuple < CallAlphabet, ReturnAlphabet, LocalAlphabet >, ext::set < PushdownStoreSymbolType >, component::Set, PushdownStoreAlphabet, PushdownStoreSymbolType, component::Value, BottomOfTheStackSymbol, ext::set < StateType >, component::Set, std::tuple < States, FinalStates >, StateType, component::Value, InitialState > ( std::move ( callAlphabet ), std::move ( returnAlphabet ), std::move ( localAlphabet ), std::move ( pushdownStoreAlphabet ), std::move ( bottomOfTheStackSymbol ), std::move ( states ), std::move ( finalStates ), std::move ( initialState ) ) {
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::VisiblyPushdownDPDA(StateType initialState, PushdownStoreSymbolType bottomOfTheStackSymbol) : VisiblyPushdownDPDA ( ext::set < StateType > { initialState }, ext::set < InputSymbolType > { }, ext::set < InputSymbolType > { }, ext::set < InputSymbolType > { }, ext::set < PushdownStoreSymbolType > { bottomOfTheStackSymbol }, initialState, bottomOfTheStackSymbol, ext::set < StateType > { }) {
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
bool VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::addCallTransition(StateType from, InputSymbolType input, StateType to, PushdownStoreSymbolType push) {
	if (!getStates().count(from)) {
		throw AutomatonException("State \"" + ext::to_string ( from ) + "\" doesn't exist.");
	}

	if (!getCallInputAlphabet().count(input)) {
		throw AutomatonException("Input symbol \"" + ext::to_string ( input ) + "\" doesn't exist.");
	}

	if (!getStates().count(to)) {
		throw AutomatonException("State \"" + ext::to_string ( to ) + "\" doesn't exist.");
	}

	if (!getPushdownStoreAlphabet().count(push)) {
		throw AutomatonException("Pushdown store symbol \"" + ext::to_string ( push ) + "\" doesn't exist.");
	}

	ext::pair<StateType, InputSymbolType> key(std::move(from), std::move(input));
	ext::pair<StateType, PushdownStoreSymbolType> value = ext::make_pair(std::move(to), std::move(push));

	if(callTransitions.find(key) != callTransitions.end() && callTransitions.find(key)->second == value)
		return false;

	for(const auto& transition : callTransitions)
		if(transition.first.first == key.first && transition.first.second == key.second)
			throw AutomatonException("Can't add transition from state \"" + ext::to_string ( key.first ) + "\" when transition reading \"" + ext::to_string ( key.second ) + "\" is present.");

	for(const auto& transition : returnTransitions)
		if(std::get<0>(transition.first) == key.first && std::get<1>(transition.first) == key.second)
			throw AutomatonException("Can't add transition from state \"" + ext::to_string ( key.first ) + "\" when transition reading \"" + ext::to_string ( key.second ) + "\" is present.");

	for(const auto& transition : localTransitions)
		if(transition.first.first == key.first && transition.first.second == key.second)
			throw AutomatonException("Can't add transition from state \"" + ext::to_string ( key.first ) + "\" when transition reading \"" + ext::to_string ( key.second ) + "\" is present.");

	callTransitions.insert ( std::move(key), std::move(value) );
	return true;
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
bool VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::addReturnTransition(StateType from, InputSymbolType input, PushdownStoreSymbolType pop, StateType to) {
	if (!getStates().count(from)) {
		throw AutomatonException("State \"" + ext::to_string ( from ) + "\" doesn't exist.");
	}

	if (!getReturnInputAlphabet().count(input)) {
		throw AutomatonException("Input symbol \"" + ext::to_string ( input ) + "\" doesn't exist.");
	}

	if (!getStates().count(to)) {
		throw AutomatonException("State \"" + ext::to_string ( to ) + "\" doesn't exist.");
	}

	if (!getPushdownStoreAlphabet().count(pop)) {
		throw AutomatonException("Pushdown store symbol \"" + ext::to_string ( pop ) + "\" doesn't exist.");
	}

	ext::tuple<StateType, InputSymbolType, PushdownStoreSymbolType> key(std::move(from), std::move(input), std::move(pop));

	if(returnTransitions.find(key) != returnTransitions.end() && returnTransitions.find(key)->second == to)
		return false;

	for(const auto& transition : callTransitions)
		if(transition.first.first == std::get<0>(key) && transition.first.second == std::get<1>(key))
			throw AutomatonException("Can't add transition from state \"" + ext::to_string ( std::get<0>(key) ) + "\" when transition reading \"" + ext::to_string ( std::get<1>(key) ) + "\" is present.");

	for(const auto& transition : returnTransitions)
		if(std::get<0>(transition.first) == std::get<0>(key) && std::get<1>(transition.first) == std::get<1>(key) && std::get<2>(transition.first) == std::get<2>(key))
			throw AutomatonException("Can't add transition from state \"" + ext::to_string ( std::get<0>(key) ) + "\" when transition reading \"" + ext::to_string ( std::get<1>(key) ) + "\" is present.");

	for(const auto& transition : localTransitions)
		if(transition.first.first == std::get<0>(key) && transition.first.second == std::get<1>(key))
			throw AutomatonException("Can't add transition from state \"" + ext::to_string ( std::get<0>(key) ) + "\" when transition reading \"" + ext::to_string ( std::get<1>(key) ) + "\" is present.");

	returnTransitions.insert ( std::move(key), std::move(to) );
	return true;
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
bool VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::addLocalTransition(StateType from, InputSymbolType input, StateType to) {
	if (!getStates().count(from)) {
		throw AutomatonException("State \"" + ext::to_string ( from ) + "\" doesn't exist.");
	}

	if (!getLocalInputAlphabet().count(input)) {
		throw AutomatonException("Input symbol \"" + ext::to_string ( input ) + "\" doesn't exist.");
	}

	if (!getStates().count(to)) {
		throw AutomatonException("State \"" + ext::to_string ( to ) + "\" doesn't exist.");
	}

	ext::pair<StateType, InputSymbolType> key(std::move(from), std::move(input));

	if(localTransitions.find(key) != localTransitions.end() && localTransitions.find(key)->second == to)
		return false;

	for(const auto& transition : callTransitions)
		if(transition.first.first == key.first && transition.first.second == key.second)
			throw AutomatonException("Can't add transition from state \"" + ext::to_string ( key.first ) + "\" when transition reading \"" + ext::to_string ( key.second ) + "\" is present.");

	for(const auto& transition : returnTransitions)
		if(std::get<0>(transition.first) == key.first && std::get<1>(transition.first) == key.second)
			throw AutomatonException("Can't add transition from state \"" + ext::to_string ( key.first ) + "\" when transition reading \"" + ext::to_string ( key.second ) + "\" is present.");

	for(const auto& transition : localTransitions)
		if(transition.first.first == key.first && transition.first.second == key.second)
			throw AutomatonException("Can't add transition from state \"" + ext::to_string ( key.first ) + "\" when transition reading \"" + ext::to_string ( key.second ) + "\" is present.");

	localTransitions.insert ( std::move ( key ), std::move ( to ) );
	return true;
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
bool VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::removeCallTransition(const StateType& from, const InputSymbolType& input, const StateType& to, const PushdownStoreSymbolType& push) {
	ext::pair<StateType, InputSymbolType> key(from, input);
	ext::pair<StateType, PushdownStoreSymbolType> value = ext::make_pair(to, push);

	if (callTransitions.find(key) == callTransitions.end())
		return false;

	if(callTransitions.find(key)->second != value)
		throw AutomatonException("Transition (\"" + ext::to_string ( from ) + "\", \"" + ext::to_string ( input ) + "\") -> \"" + ext::to_string ( to ) + "\" doesn't exist.");

	callTransitions.erase(key);
	return true;
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
bool VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::removeReturnTransition(const StateType& from, const InputSymbolType& input, const PushdownStoreSymbolType& pop, const StateType& to) {
	ext::tuple<StateType, InputSymbolType, PushdownStoreSymbolType> key(from, input, pop);

	if (returnTransitions.find(key) == returnTransitions.end())
		return false;

	if(returnTransitions.find(key)->second != to)
		throw AutomatonException( "Transition (\"" + ext::to_string ( from ) + "\", \"" + ext::to_string ( input ) + "\") -> \"" + ext::to_string ( to ) + "\" doesn't exist.");

	returnTransitions.erase(key);
	return true;
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
bool VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::removeLocalTransition(const StateType& from, const InputSymbolType& input, const StateType& to) {
	ext::pair<StateType, InputSymbolType> key(from, input);

	if (localTransitions.find(key) == localTransitions.end())
		return false;

	if(localTransitions.find(key)->second != to)
		throw AutomatonException("Transition (\"" + ext::to_string ( from ) + "\", \"" + ext::to_string ( input ) + "\") -> \"" + ext::to_string ( to ) + "\" doesn't exist.");

	localTransitions.erase(key);
	return true;
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
const ext::map < ext::pair < StateType, InputSymbolType >, ext::pair < StateType, PushdownStoreSymbolType > > & VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::getCallTransitions ( ) const & {
	return callTransitions;
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
ext::map < ext::pair < StateType, InputSymbolType >, ext::pair < StateType, PushdownStoreSymbolType > > && VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::getCallTransitions ( ) && {
	return std::move ( callTransitions );
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
const ext::map < ext::tuple < StateType, InputSymbolType, PushdownStoreSymbolType >, StateType > & VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::getReturnTransitions ( ) const & {
	return returnTransitions;
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
ext::map < ext::tuple < StateType, InputSymbolType, PushdownStoreSymbolType >, StateType > && VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::getReturnTransitions ( ) && {
	return std::move ( returnTransitions );
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
const ext::map < ext::pair < StateType, InputSymbolType >, StateType > & VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::getLocalTransitions ( ) const & {
	return localTransitions;
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
ext::map < ext::pair < StateType, InputSymbolType >, StateType > && VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::getLocalTransitions ( ) && {
	return std::move ( localTransitions );
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
int VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::compare(const VisiblyPushdownDPDA& other) const {
	auto first = ext::tie(getStates(), getCallInputAlphabet(), getReturnInputAlphabet(), getLocalInputAlphabet(), getInitialState(), getFinalStates(), getPushdownStoreAlphabet(), getBottomOfTheStackSymbol(), callTransitions, returnTransitions, localTransitions);
	auto second = ext::tie(other.getStates(), other.getCallInputAlphabet(), other.getReturnInputAlphabet(), other.getLocalInputAlphabet(), other.getInitialState(), other.getFinalStates(), other.getPushdownStoreAlphabet(), other.getBottomOfTheStackSymbol(), other.callTransitions, other.returnTransitions, other.localTransitions);

	static ext::compare<decltype(first)> comp;
	return comp(first, second);
}

template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >::operator std::string ( ) const {
	std::stringstream ss;
	ss << *this;
	return ss.str();
}

} /* namespace automaton */

namespace core {

/**
 * Helper class specifying constraints for the automaton's internal call input alphabet component.
 *
 * \tparam InputSymbolType used for the terminal alphabet of the automaton.
 * \tparam PushdownSymbolType used for the pushdown store alphabet of the automaton.
 * \tparam StateType used for the terminal alphabet of the automaton.
 */
template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
class SetConstraint< automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >, InputSymbolType, automaton::CallAlphabet > {
public:
	/**
	 * Returns true if the symbol is still used in some transition of the automaton.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 *
	 * \returns true if the symbol is used, false othervise
	 */
	static bool used ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const InputSymbolType & symbol ) {
		for ( const std::pair<const ext::pair<StateType, InputSymbolType>, ext::pair<StateType, PushdownStoreSymbolType> >& callTransition : automaton.getCallTransitions())
			if (symbol == callTransition.first.second)
				return true;

		return false;
	}

	/**
	 * Returns true as all symbols are possibly available to be elements of the call input alphabet.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 *
	 * \returns true
	 */
	static bool available ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > &, const InputSymbolType & ) {
		return true;
	}

	/**
	 * All symbols are valid as call input symbols.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 */
	static void valid ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const InputSymbolType & symbol ) {
		if(automaton.getLocalInputAlphabet().count(symbol))
			throw automaton::AutomatonException("Input symbol " + ext::to_string ( symbol ) + " already in local alphabet");
		if(automaton.getReturnInputAlphabet().count(symbol))
			throw automaton::AutomatonException("Input symbol " + ext::to_string ( symbol ) + " already in return alphabet");
	}
};

/**
 * Helper class specifying constraints for the automaton's internal return input alphabet component.
 *
 * \tparam InputSymbolType used for the terminal alphabet of the automaton.
 * \tparam PushdownSymbolType used for the pushdown store alphabet of the automaton.
 * \tparam StateType used for the terminal alphabet of the automaton.
 */
template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
class SetConstraint< automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >, InputSymbolType, automaton::ReturnAlphabet > {
public:
	/**
	 * Returns true if the symbol is still used in some transition of the automaton.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 *
	 * \returns true if the symbol is used, false othervise
	 */
	static bool used ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const InputSymbolType & symbol ) {
		for ( const std::pair<const ext::tuple<StateType, InputSymbolType, PushdownStoreSymbolType>, StateType>& returnTransition : automaton.getReturnTransitions())
			if (symbol == std::get<1>(returnTransition.first))
				return true;

		return false;
	}

	/**
	 * Returns true as all symbols are possibly available to be elements of the return input alphabet.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 *
	 * \returns true
	 */
	static bool available ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > &, const InputSymbolType & ) {
		return true;
	}

	/**
	 * All symbols are valid as return input symbols.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 */
	static void valid ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const InputSymbolType & symbol ) {
		if(automaton.getLocalInputAlphabet().count(symbol))
			throw automaton::AutomatonException("Input symbol " + ext::to_string ( symbol ) + " already in local alphabet");
		if(automaton.getCallInputAlphabet().count(symbol))
			throw automaton::AutomatonException("Input symbol " + ext::to_string ( symbol ) + " already in call alphabet");
	}
};

/**
 * Helper class specifying constraints for the automaton's internal local input alphabet component.
 *
 * \tparam InputSymbolType used for the terminal alphabet of the automaton.
 * \tparam PushdownSymbolType used for the pushdown store alphabet of the automaton.
 * \tparam StateType used for the terminal alphabet of the automaton.
 */
template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
class SetConstraint< automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >, InputSymbolType, automaton::LocalAlphabet > {
public:
	/**
	 * Returns true if the symbol is still used in some transition of the automaton.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 *
	 * \returns true if the symbol is used, false othervise
	 */
	static bool used ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const InputSymbolType & symbol ) {
		for ( const std::pair<const ext::pair<StateType, InputSymbolType>, StateType>& localTransition : automaton.getLocalTransitions())
			if (symbol == localTransition.first.second)
				return true;

		return false;
	}

	/**
	 * Returns true as all symbols are possibly available to be elements of the local input alphabet.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 *
	 * \returns true
	 */
	static bool available ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > &, const InputSymbolType & ) {
		return true;
	}

	/**
	 * All symbols are valid as local input symbols.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 */
	static void valid ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const InputSymbolType & symbol ) {
		if(automaton.getReturnInputAlphabet().count(symbol))
			throw automaton::AutomatonException("Input symbol " + ext::to_string ( symbol ) + " already in return alphabet");
		if(automaton.getCallInputAlphabet().count(symbol))
			throw automaton::AutomatonException("Input symbol " + ext::to_string ( symbol ) + " already in call alphabet");
	}
};

/**
 * Helper class specifying constraints for the automaton's internal pushdown store alphabet component.
 *
 * \tparam InputSymbolType used for the terminal alphabet of the automaton.
 * \tparam PushdownSymbolType used for the pushdown store alphabet of the automaton.
 * \tparam StateType used for the terminal alphabet of the automaton.
 */
template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
class SetConstraint< automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >, PushdownStoreSymbolType, automaton::PushdownStoreAlphabet > {
public:
	/**
	 * Returns true if the symbol is still used in some transition of the automaton.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 *
	 * \returns true if the symbol is used, false othervise
	 */
	static bool used ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const PushdownStoreSymbolType & symbol ) {
		for ( const std::pair<const ext::pair<StateType, InputSymbolType>, ext::pair<StateType, PushdownStoreSymbolType> >& callTransition : automaton.getCallTransitions())
			if (symbol == callTransition.second.second)
				return true;

		for ( const std::pair<const ext::tuple<StateType, InputSymbolType, PushdownStoreSymbolType>, StateType>& returnTransition : automaton.getReturnTransitions())
			if (symbol == std::get<2>(returnTransition.first))
				return true;

		if(automaton.getBottomOfTheStackSymbol() == symbol)
			return true;

		return false;
	}

	/**
	 * Returns true as all symbols are possibly available to be elements of the pushdown store alphabet.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 *
	 * \returns true
	 */
	static bool available ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > &, const PushdownStoreSymbolType & ) {
		return true;
	}

	/**
	 * All symbols are valid as pushdown store symbols.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 */
	static void valid ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > &, const PushdownStoreSymbolType & ) {
	}
};

/**
 * Helper class specifying constraints for the automaton's internal bottom of the stack symbol element.
 *
 * \tparam InputSymbolType used for the terminal alphabet of the automaton.
 * \tparam PushdownSymbolType used for the pushdown store alphabet of the automaton.
 * \tparam StateType used for the terminal alphabet of the automaton.
 */
template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
class ElementConstraint< automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >, PushdownStoreSymbolType, automaton::BottomOfTheStackSymbol > {
public:
	/**
	 * Determines whether the bottom of the stack symbol is available in the automaton's pushdown store alphabet.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 *
	 * \returns true if the pushdown store symbol is already in the pushdown store alphabet of the automaton
	 */
	static bool available ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const PushdownStoreSymbolType & symbol ) {
		return automaton.template accessComponent < automaton::PushdownStoreAlphabet > ( ).get ( ).count ( symbol );
	}

	/**
	 * All pushdown store symbols are valid as a bottom of the stack symbol symbol of the automaton.
	 *
	 * \param automaton the tested automaton
	 * \param symbol the tested symbol
	 */
	static void valid ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > &, const PushdownStoreSymbolType & ) {
	}
};

/**
 * Helper class specifying constraints for the automaton's internal states component.
 *
 * \tparam InputSymbolType used for the terminal alphabet of the automaton.
 * \tparam PushdownSymbolType used for the pushdown store alphabet of the automaton.
 * \tparam StateType used for the terminal alphabet of the automaton.
 */
template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
class SetConstraint< automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >, StateType, automaton::States > {
public:
	/**
	 * Returns true if the state is still used in some transition of the automaton.
	 *
	 * \param automaton the tested automaton
	 * \param state the tested state
	 *
	 * \returns true if the state is used, false othervise
	 */
	static bool used ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const StateType & state ) {
		if ( automaton.getInitialState ( ) == state )
			return true;

		if ( automaton.getFinalStates ( ).count ( state ) )
			return true;

		for ( const std::pair<const ext::pair<StateType, InputSymbolType>, ext::pair<StateType, PushdownStoreSymbolType> >& callTransition : automaton.getCallTransitions())
			if (state == callTransition.first.first || callTransition.second.first == state)
				return true;

		for ( const std::pair<const ext::tuple<StateType, InputSymbolType, PushdownStoreSymbolType>, StateType>& returnTransition : automaton.getReturnTransitions())
			if (state == std::get<0>(returnTransition.first) || returnTransition.second == state)
				return true;

		for ( const std::pair<const ext::pair<StateType, InputSymbolType>, StateType>& localTransition : automaton.getLocalTransitions())
			if (state == localTransition.first.first || localTransition.second == state)
				return true;

		return false;
	}

	/**
	 * Returns true as all states are possibly available to be elements of the states.
	 *
	 * \param automaton the tested automaton
	 * \param state the tested state
	 *
	 * \returns true
	 */
	static bool available ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > &, const StateType & ) {
		return true;
	}

	/**
	 * All states are valid as a state of the automaton.
	 *
	 * \param automaton the tested automaton
	 * \param state the tested state
	 */
	static void valid ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > &, const StateType & ) {
	}
};

/**
 * Helper class specifying constraints for the automaton's internal final states component.
 *
 * \tparam InputSymbolType used for the terminal alphabet of the automaton.
 * \tparam PushdownSymbolType used for the pushdown store alphabet of the automaton.
 * \tparam StateType used for the terminal alphabet of the automaton.
 */
template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
class SetConstraint< automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >, StateType, automaton::FinalStates > {
public:
	/**
	 * Returns false. Final state is only a mark that the automaton itself does require further.
	 *
	 * \param automaton the tested automaton
	 * \param state the tested state
	 *
	 * \returns false
	 */
	static bool used ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > &, const StateType & ) {
		return false;
	}

	/**
	 * Determines whether the state is available in the automaton's states set.
	 *
	 * \param automaton the tested automaton
	 * \param state the tested state
	 *
	 * \returns true if the state is already in the set of states of the automaton
	 */
	static bool available ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const StateType & state ) {
		return automaton.template accessComponent < automaton::States > ( ).get ( ).count ( state );
	}

	/**
	 * All states are valid as a final state of the automaton.
	 *
	 * \param automaton the tested automaton
	 * \param state the tested state
	 */
	static void valid ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > &, const StateType & ) {
	}
};

/**
 * Helper class specifying constraints for the automaton's internal initial state element.
 *
 * \tparam InputSymbolType used for the terminal alphabet of the automaton.
 * \tparam PushdownSymbolType used for the pushdown store alphabet of the automaton.
 * \tparam StateType used for the terminal alphabet of the automaton.
 */
template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
class ElementConstraint< automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType >, StateType, automaton::InitialState > {
public:
	/**
	 * Determines whether the state is available in the automaton's states set.
	 *
	 * \param automaton the tested automaton
	 * \param state the tested state
	 *
	 * \returns true if the state is already in the set of states of the automaton
	 */
	static bool available ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & automaton, const StateType & state ) {
		return automaton.template accessComponent < automaton::States > ( ).get ( ).count ( state );
	}

	/**
	 * All states are valid as an initial state of the automaton.
	 *
	 * \param automaton the tested automaton
	 * \param state the tested state
	 */
	static void valid ( const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > &, const StateType & ) {
	}
};

/**
 * Helper for normalisation of types specified by templates used as internal datatypes of symbols and states.
 *
 * \returns new instance of the automaton with default template parameters or unmodified instance if the template parameters were already the default ones
 */
template < class InputSymbolType, class PushdownStoreSymbolType, class StateType >
struct normalize < automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > > {
	static automaton::VisiblyPushdownDPDA < > eval ( automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > && value ) {
		ext::set < DefaultSymbolType > call_alphabet = alphabet::SymbolNormalize::normalizeAlphabet ( std::move ( value ).getCallInputAlphabet ( ) );
		ext::set < DefaultSymbolType > return_alphabet = alphabet::SymbolNormalize::normalizeAlphabet ( std::move ( value ).getReturnInputAlphabet ( ) );
		ext::set < DefaultSymbolType > local_alphabet = alphabet::SymbolNormalize::normalizeAlphabet ( std::move ( value ).getLocalInputAlphabet ( ) );
		ext::set < DefaultSymbolType > pushdownAlphabet = alphabet::SymbolNormalize::normalizeAlphabet ( std::move ( value ).getPushdownStoreAlphabet ( ) );
		DefaultSymbolType initialSymbol = alphabet::SymbolNormalize::normalizeSymbol ( std::move ( value ).getBottomOfTheStackSymbol ( ) );
		ext::set < DefaultStateType > states = automaton::AutomatonNormalize::normalizeStates ( std::move ( value ).getStates ( ) );
		DefaultStateType initialState = automaton::AutomatonNormalize::normalizeState ( std::move ( value ).getInitialState ( ) );
		ext::set < DefaultStateType > finalStates = automaton::AutomatonNormalize::normalizeStates ( std::move ( value ).getFinalStates ( ) );

		automaton::VisiblyPushdownDPDA < > res ( std::move ( states ), std::move ( call_alphabet ), std::move ( return_alphabet ), std::move ( local_alphabet ), std::move ( pushdownAlphabet ), std::move ( initialState ), std::move ( initialSymbol ), std::move ( finalStates ) );

		for ( std::pair < ext::pair < StateType, InputSymbolType >, ext::pair < StateType, PushdownStoreSymbolType > > && transition : ext::make_mover ( std::move ( value ).getCallTransitions ( ) ) ) {
			DefaultStateType to = automaton::AutomatonNormalize::normalizeState ( std::move ( transition.second.first ) );
			DefaultSymbolType push = alphabet::SymbolNormalize::normalizeSymbol ( std::move ( transition.second.second ) );

			DefaultStateType from = automaton::AutomatonNormalize::normalizeState ( std::move ( transition.first.first ) );
			DefaultSymbolType input = alphabet::SymbolNormalize::normalizeSymbol ( std::move ( transition.first.second ) );

			res.addCallTransition ( std::move ( from ), std::move ( input ), std::move ( to ), std::move ( push ) );
		}

		for ( std::pair < ext::tuple < StateType, InputSymbolType, PushdownStoreSymbolType >, StateType > && transition : ext::make_mover ( std::move ( value ).getReturnTransitions ( ) ) ) {
			DefaultStateType to = automaton::AutomatonNormalize::normalizeState ( std::move ( transition.second ) );

			DefaultStateType from = automaton::AutomatonNormalize::normalizeState ( std::move ( std::get < 0 > ( transition.first ) ) );
			DefaultSymbolType input = alphabet::SymbolNormalize::normalizeSymbol ( std::move ( std::get < 1 > ( transition.first ) ) );
			DefaultSymbolType pop = alphabet::SymbolNormalize::normalizeSymbol ( std::move ( std::get < 2 > ( transition.first ) ) );

			res.addReturnTransition ( std::move ( from ), std::move ( input ), std::move ( pop ), std::move ( to ) );
		}

		for ( std::pair < ext::pair < StateType, InputSymbolType >, StateType > && transition : ext::make_mover ( std::move ( value ).getLocalTransitions ( ) ) ) {
			DefaultStateType to = automaton::AutomatonNormalize::normalizeState ( std::move ( transition.second ) );

			DefaultStateType from = automaton::AutomatonNormalize::normalizeState ( std::move ( transition.first.first ) );
			DefaultSymbolType input = alphabet::SymbolNormalize::normalizeSymbol ( std::move ( transition.first.second ) );

			res.addLocalTransition ( std::move ( from ), std::move ( input ), std::move ( to ) );
		}

		return res;
	}
};

} /* namespace core */

extern template class automaton::VisiblyPushdownDPDA < >;

#endif /* VISIBLY_PUSHDOWN_DPDA_H_ */
