/*
 * AutomatonCompare.h
 *
 *  Created on: Apr 1, 2013
 *      Author: honza
 */

#pragma once

#include "automaton/FSM/DFA.h"
#include "automaton/FSM/NFA.h"
#include "automaton/FSM/MultiInitialStateNFA.h"
#include "automaton/FSM/EpsilonNFA.h"
#include "automaton/FSM/ExtendedNFA.h"
#include "automaton/FSM/CompactNFA.h"
#include "automaton/FSM/CompactDFA.h"
#include "automaton/TA/DFTA.h"
#include "automaton/TA/NFTA.h"
#include "automaton/PDA/NPDA.h"
#include "automaton/PDA/DPDA.h"
#include "automaton/PDA/InputDrivenNPDA.h"
#include "automaton/PDA/InputDrivenDPDA.h"
#include "automaton/PDA/VisiblyPushdownNPDA.h"
#include "automaton/PDA/VisiblyPushdownDPDA.h"
#include "automaton/PDA/RealTimeHeightDeterministicNPDA.h"
#include "automaton/PDA/RealTimeHeightDeterministicDPDA.h"
#include "automaton/PDA/SinglePopNPDA.h"
#include "automaton/PDA/SinglePopDPDA.h"
#include "automaton/TM/OneTapeDTM.h"

namespace compare {

class AutomatonCompare {
public:
	template<class SymbolType, class StateType>
	static bool compare(const automaton::DFA < SymbolType, StateType > & a, const automaton::DFA < SymbolType, StateType > & b);

	template<class SymbolType, class StateType>
	static bool compare(const automaton::NFA < SymbolType, StateType > & a, const automaton::NFA < SymbolType, StateType > & b);

	template<class SymbolType, class StateType>
	static bool compare(const automaton::MultiInitialStateNFA < SymbolType, StateType > & a, const automaton::MultiInitialStateNFA < SymbolType, StateType > & b);

	template<class SymbolType, class StateType>
	static bool compare(const automaton::EpsilonNFA < SymbolType, StateType > & a, const automaton::EpsilonNFA < SymbolType, StateType > & b);

	template<class SymbolType, class StateType>
	static bool compare(const automaton::ExtendedNFA < SymbolType, StateType > & a, const automaton::ExtendedNFA < SymbolType, StateType > & b);

	template<class SymbolType, class StateType>
	static bool compare(const automaton::CompactDFA < SymbolType, StateType > & a, const automaton::CompactDFA < SymbolType, StateType > & b);

	template<class SymbolType, class StateType>
	static bool compare(const automaton::CompactNFA < SymbolType, StateType > & a, const automaton::CompactNFA < SymbolType, StateType > & b);

	template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
	static bool compare(const automaton::DPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::DPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b);

	template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
	static bool compare(const automaton::NPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::NPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b);

	template<class SymbolType, class StateType>
	static bool compare(const automaton::DFTA < SymbolType, StateType > & a, const automaton::DFTA < SymbolType, StateType > & b);

	template<class SymbolType, class StateType>
	static bool compare(const automaton::NFTA < SymbolType, StateType > & a, const automaton::NFTA < SymbolType, StateType > & b);

	template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
	static bool compare(const automaton::InputDrivenDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::InputDrivenDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b);

	template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
	static bool compare(const automaton::InputDrivenNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::InputDrivenNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b);

	template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
	static bool compare(const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b);

	template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
	static bool compare(const automaton::VisiblyPushdownNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::VisiblyPushdownNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b);

	template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
	static bool compare(const automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b);

	template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
	static bool compare(const automaton::RealTimeHeightDeterministicNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::RealTimeHeightDeterministicNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b);

	template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
	static bool compare(const automaton::SinglePopDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::SinglePopDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b);

	template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
	static bool compare(const automaton::SinglePopNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::SinglePopNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b);

	template<class SymbolType, class StateType>
	static bool compare(const automaton::OneTapeDTM < SymbolType, StateType > & a, const automaton::OneTapeDTM < SymbolType, StateType > & b);
};

template<class SymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::DFA < SymbolType, StateType > & a, const automaton::DFA < SymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialState()   == b.getInitialState()   &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class SymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::MultiInitialStateNFA < SymbolType, StateType > & a, const automaton::MultiInitialStateNFA < SymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialStates()  == b.getInitialStates()  &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class SymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::NFA < SymbolType, StateType > & a, const automaton::NFA < SymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialState()   == b.getInitialState()   &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class SymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::EpsilonNFA < SymbolType, StateType > & a, const automaton::EpsilonNFA < SymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialState()   == b.getInitialState()   &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class SymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::ExtendedNFA < SymbolType, StateType > & a, const automaton::ExtendedNFA < SymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialState()   == b.getInitialState()   &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class SymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::CompactDFA < SymbolType, StateType > & a, const automaton::CompactDFA < SymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialState()   == b.getInitialState()   &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class SymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::CompactNFA < SymbolType, StateType > & a, const automaton::CompactNFA < SymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialState()   == b.getInitialState()   &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class SymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::DFTA < SymbolType, StateType > & a, const automaton::DFTA < SymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class SymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::NFTA < SymbolType, StateType > & a, const automaton::NFTA < SymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::DPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::DPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialState()   == b.getInitialState()   &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
//			a.getPushdownStoreAlphabet()  == b.getPushdownStoreAlphabet()  &&
			a.getInitialSymbol()  == b.getInitialSymbol()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::NPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::NPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialState()   == b.getInitialState()   &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
//			a.getPushdownStoreAlphabet()  == b.getPushdownStoreAlphabet()  &&
			a.getInitialSymbol()  == b.getInitialSymbol()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::InputDrivenDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::InputDrivenDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b) {
	return  	a.getFinalStates()             == b.getFinalStates()             &&
			a.getInitialState()            == b.getInitialState()            &&
//			a.getInputAlphabet()           == b.getInputAlphabet()           &&
//			a.getPushdownStoreAlphabet()   == b.getPushdownStoreAlphabet()           &&
			a.getInitialSymbol()           == b.getInitialSymbol()           &&
			a.getStates()                  == b.getStates()                  &&
			a.getPushdownStoreOperations() == b.getPushdownStoreOperations() &&
			a.getTransitions()             == b.getTransitions()             ;
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::InputDrivenNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::InputDrivenNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b) {
	return  	a.getFinalStates()             == b.getFinalStates()             &&
			a.getInitialState()            == b.getInitialState()            &&
//			a.getInputAlphabet()           == b.getInputAlphabet()           &&
//			a.getPushdownStoreAlphabet()   == b.getPushdownStoreAlphabet()           &&
			a.getInitialSymbol()           == b.getInitialSymbol()           &&
			a.getStates()                  == b.getStates()                  &&
			a.getPushdownStoreOperations() == b.getPushdownStoreOperations() &&
			a.getTransitions()             == b.getTransitions()             ;
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::VisiblyPushdownDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b) {
	return  	a.getFinalStates()            == b.getFinalStates()            &&
			a.getInitialState()           == b.getInitialState()           &&
//			a.getCallInputAlphabet()      == b.getCallInputAlphabet()      &&
//			a.getReturnnputAlphabet()     == b.getReturnInputAlphabet()    &&
//			a.getLocalInputAlphabet()     == b.getLocalInputAlphabet()     &&
//			a.getPushdownStoreAlphabet()  == b.getPushdownStoreAlphabet()          &&
			a.getBottomOfTheStackSymbol() == b.getBottomOfTheStackSymbol() &&
			a.getStates()                 == b.getStates()                 &&
			a.getCallTransitions()        == b.getCallTransitions()        &&
			a.getReturnTransitions()      == b.getReturnTransitions()      &&
			a.getLocalTransitions()       == b.getLocalTransitions()       ;
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::VisiblyPushdownNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::VisiblyPushdownNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b) {
	return  	a.getFinalStates()            == b.getFinalStates()            &&
			a.getInitialStates()          == b.getInitialStates()          &&
//			a.getCallInputAlphabet()      == b.getCallInputAlphabet()      &&
//			a.getReturnnputAlphabet()     == b.getReturnInputAlphabet()    &&
//			a.getLocalInputAlphabet()     == b.getLocalInputAlphabet()     &&
//			a.getPushdownStoreAlphabet()  == b.getPushdownStoreAlphabet()          &&
			a.getBottomOfTheStackSymbol() == b.getBottomOfTheStackSymbol() &&
			a.getStates()                 == b.getStates()                 &&
			a.getCallTransitions()        == b.getCallTransitions()        &&
			a.getReturnTransitions()      == b.getReturnTransitions()      &&
			a.getLocalTransitions()       == b.getLocalTransitions()       ;
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b) {
	return  	a.getFinalStates()            == b.getFinalStates()            &&
			a.getInitialState()           == b.getInitialState()           &&
//			a.getInputAlphabet()          == b.getInputAlphabet()          &&
//			a.getPushdownStoreAlphabet()  == b.getPushdownStoreAlphabet()          &&
			a.getBottomOfTheStackSymbol() == b.getBottomOfTheStackSymbol() &&
			a.getStates()                 == b.getStates()                 &&
			a.getCallTransitions()        == b.getCallTransitions()        &&
			a.getReturnTransitions()      == b.getReturnTransitions()      &&
			a.getLocalTransitions()       == b.getLocalTransitions()       ;
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::RealTimeHeightDeterministicNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::RealTimeHeightDeterministicNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b) {
	return  	a.getFinalStates()            == b.getFinalStates()            &&
			a.getInitialStates()          == b.getInitialStates()          &&
//			a.getInputAlphabet()          == b.getInputAlphabet()          &&
//			a.getPushdownStoreAlphabet()  == b.getPushdownStoreAlphabet()          &&
			a.getBottomOfTheStackSymbol() == b.getBottomOfTheStackSymbol() &&
			a.getStates()                 == b.getStates()                 &&
			a.getCallTransitions()        == b.getCallTransitions()        &&
			a.getReturnTransitions()      == b.getReturnTransitions()      &&
			a.getLocalTransitions()       == b.getLocalTransitions()       ;
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::SinglePopDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::SinglePopDPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialState()   == b.getInitialState()   &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
//			a.getPushdownStoreAlphabet()  == b.getPushdownStoreAlphabet()  &&
			a.getInitialSymbol()  == b.getInitialSymbol()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class InputSymbolType, class PushdownStoreSymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::SinglePopNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & a, const automaton::SinglePopNPDA < InputSymbolType, PushdownStoreSymbolType, StateType > & b) {
	return  	a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialState()   == b.getInitialState()   &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
//			a.getPushdownStoreAlphabet()  == b.getPushdownStoreAlphabet()  &&
			a.getInitialSymbol()  == b.getInitialSymbol()  &&
			a.getStates()         == b.getStates()         &&
			a.getTransitions()    == b.getTransitions()    ;
}

template<class SymbolType, class StateType>
bool AutomatonCompare::compare(const automaton::OneTapeDTM < SymbolType, StateType > & a, const automaton::OneTapeDTM < SymbolType, StateType > & b) {
	return  	a.getBlankSymbol()    == b.getBlankSymbol()    &&
			a.getFinalStates()    == b.getFinalStates()    &&
			a.getInitialState()   == b.getInitialState()   &&
//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
			a.getStates()         == b.getStates()         &&
//			a.getTapeAlphabet()   == b.getTapeAlphabet()   &&
			a.getTransitions()    == b.getTransitions()    ;
}

} /* namespace compare */

