/*
 * Determinize.h
 *
 *  Created on: 16. 1. 2014
 *	  Author: Jan Vesely
 */

#ifndef DETERMINIZE_H_
#define DETERMINIZE_H_

#include <alib/set>

#include <automaton/Automaton.h>
#include <automaton/AutomatonFeatures.h>

namespace automaton {

namespace determinize {

/**
 * Class for running determinization algorithm on fsm.
 */
class Determinize {
public:

	static automaton::DFA<> determinize(const automaton::DFA<>& nfa);

	/**
	 * @param nfsm nondeterministic final-state machine given for determinization
	 * @return DFA
	 * Runs determinization algorithm on nondeterministic fsm given in constructor.
	 */
	template < class SymbolType, class StateType >
	static automaton::DFA < SymbolType, ext::set < StateType > > determinize(const automaton::NFA < SymbolType, StateType > & nfa);

	template < class SymbolType, class StateType >
	static automaton::DFA < SymbolType, ext::set < StateType > > determinize(const automaton::MultiInitialStateNFA < SymbolType, StateType > & nfa);

	static automaton::DPDA < > determinize(const automaton::DPDA < > & dpda);
	static automaton::DPDA < > determinize(const automaton::NPDA < > & dpda);
	static automaton::SinglePopDPDA < > determinize(const automaton::SinglePopDPDA < > & dpda);
	static automaton::VisiblyPushdownDPDA < > determinize(const automaton::VisiblyPushdownDPDA < > & nondeterministic);
	static automaton::VisiblyPushdownDPDA < > determinize(const automaton::VisiblyPushdownNPDA < > & nondeterministic);
	static automaton::InputDrivenDPDA < > determinize(const automaton::InputDrivenDPDA < > & nfa);
	static automaton::InputDrivenDPDA < > determinize(const automaton::InputDrivenNPDA < > & nfa);
	static automaton::RealTimeHeightDeterministicDPDA < > determinize(const automaton::RealTimeHeightDeterministicDPDA < > & nondeterministic);
	static automaton::RealTimeHeightDeterministicDPDA < > determinize(const automaton::RealTimeHeightDeterministicNPDA < > & nondeterministic);
	static automaton::DFTA < > determinize(const automaton::DFTA < > & nfta);
	static automaton::DFTA < > determinize(const automaton::NFTA < > & nfta);

	static automaton::OneTapeDTM<> determinize(const automaton::OneTapeDTM<>& nfta);
};

} /* namespace determinize */

} /* namespace automaton */

#include "DeterminizeNFAPart.hxx"

#endif /* DETERMINIZE_H_ */