#include "FSMSingleInitialStateTest.h"

#include "automaton/simplify/SingleInitialState.h"
#include "automaton/determinize/Determinize.h"
#include "automaton/simplify/Normalize.h"
#include "automaton/simplify/Minimize.h"

#include "automaton/FSM/MultiInitialStateNFA.h"

CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( FSMSingleInitialStateTest, "automaton" );
CPPUNIT_TEST_SUITE_REGISTRATION( FSMSingleInitialStateTest );

void FSMSingleInitialStateTest::setUp() {
}

void FSMSingleInitialStateTest::tearDown() {
}

void FSMSingleInitialStateTest::testSingleInitialState() {
	DefaultStateType q  = DefaultStateType ("q");
	DefaultStateType q0 = DefaultStateType ("q0");
	DefaultStateType q1 = DefaultStateType ("q1");
	DefaultStateType q2 = DefaultStateType ("q2");
	DefaultStateType q3 = DefaultStateType ("q3");

	DefaultSymbolType a = DefaultSymbolType('a');
	DefaultSymbolType b = DefaultSymbolType('b');

	automaton::MultiInitialStateNFA < > automaton1;
	automaton1.setStates({q0, q1, q2, q3});
	automaton1.setInitialStates({q0, q1, q2});
	automaton1.setFinalStates({q3});
	automaton1.setInputAlphabet({a, b});
	automaton1.addTransition(q0, a, q1);
	automaton1.addTransition(q1, b, q2);
	automaton1.addTransition(q2, a, q3);

	automaton::NFA < > automaton2 = automaton::simplify::SingleInitialState::convert(automaton1);

	automaton::NFA < > automaton3(q);
	automaton3.setStates({q, q1, q2, q3});
	automaton3.setFinalStates({q3});
	automaton3.setInputAlphabet({a, b});
	automaton3.addTransition(q, a, q3);
	automaton3.addTransition(q, b, q2);
	automaton3.addTransition(q, a, q1);
	automaton3.addTransition(q1, b, q2);
	automaton3.addTransition(q2, a, q3);

	automaton::DFA<> dfa2 = automaton::simplify::Minimize::minimize(automaton::determinize::Determinize::determinize(automaton2));
	automaton::DFA<> dfa3 = automaton::simplify::Minimize::minimize(automaton::determinize::Determinize::determinize(automaton3));

	CPPUNIT_ASSERT(automaton::simplify::Normalize::normalize(dfa2) == automaton::simplify::Normalize::normalize(dfa3));
}