#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"

#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y))

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

void FSMSingleInitialStateTest::setUp() {
}

void FSMSingleInitialStateTest::tearDown() {
}

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

	alphabet::Symbol a = alphabet::Symbol('a');
	alphabet::Symbol b = alphabet::Symbol('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));
}