package pl.edu.amu.wmi.daut.base;
import java.util.HashSet;
import junit.framework.TestCase;
import java.util.List;
import java.util.ArrayList;
/**
* Testy różnych operacji na automatach.
*/
public class TestAutomataOperations extends TestCase {
/**
* Test prostego automatu.
*/
public final void testSimpleAutomaton() {
AutomatonSpecification automatonA = new NaiveAutomatonSpecification();
State q0 = automatonA.addState();
State q1 = automatonA.addState();
automatonA.addTransition(q0, q1, new CharTransitionLabel('a'));
automatonA.addLoop(q1, new CharTransitionLabel('a'));
automatonA.addLoop(q1, new CharTransitionLabel('b'));
automatonA.markAsInitial(q0);
automatonA.markAsFinal(q1);
AutomatonSpecification automatonB = new NaiveAutomatonSpecification();
State q10 = automatonB.addState();
State q11 = automatonB.addState();
State q12 = automatonB.addState();
automatonB.addTransition(q10, q11, new CharTransitionLabel('a'));
automatonB.addTransition(q10, q11, new CharTransitionLabel('b'));
automatonB.addTransition(q11, q12, new CharTransitionLabel('a'));
automatonB.addTransition(q11, q12, new CharTransitionLabel('b'));
automatonB.markAsInitial(q10);
automatonB.markAsFinal(q12);
// proszę odkomentować, kiedy AutomataOperations.intersection
// będzie gotowe!!!
// AutomatonSpecification Result = AutomataOperations.intersection(automatonA, automatonB);
// AutomatonByRecursion automaton = AutomatonByRecursion(Result);
// assertTrue(automaton.accepts("aa"));
// assertTrue(automaton.accepts("ab"));
// assertFalse(automaton.accepts(""));
// assertFalse(automaton.accepts("a"));
}
/**
* Test sprawdza metode Sum w AutomataOperations A.
*/
public final void testSumA() {
AutomatonSpecification automatonA = new NaiveAutomatonSpecification();
State q0 = automatonA.addState();
State q1 = automatonA.addState();
automatonA.addTransition(q0, q1, new CharTransitionLabel('a'));
automatonA.addLoop(q1, new CharTransitionLabel('a'));
automatonA.addLoop(q1, new CharTransitionLabel('b'));
automatonA.markAsInitial(q0);
automatonA.markAsFinal(q1);
AutomatonSpecification automatonB = new NaiveAutomatonSpecification();
State q0B = automatonB.addState();
State q1B = automatonB.addState();
State q2B = automatonB.addState();
automatonB.addTransition(q0B, q1B, new CharTransitionLabel('a'));
automatonB.addTransition(q0B, q1B, new CharTransitionLabel('b'));
automatonB.addTransition(q1B, q2B, new CharTransitionLabel('a'));
automatonB.addTransition(q1B, q2B, new CharTransitionLabel('b'));
automatonB.markAsInitial(q0B);
automatonB.markAsFinal(q2B);
AutomatonSpecification result = AutomataOperations.sum(automatonA, automatonB);
NondeterministicAutomatonByThompsonApproach automaton = new
NondeterministicAutomatonByThompsonApproach(result);
assertTrue(automaton.accepts("aa"));
assertTrue(automaton.accepts("ba"));
assertTrue(automaton.accepts("aaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaa"));
assertTrue(automaton.accepts("bb"));
assertTrue(automaton.accepts("abbbbabbbabbb"));
assertFalse(automaton.accepts("bbb"));
assertFalse(automaton.accepts("tegomaniezakceptowac"));
assertFalse(automaton.accepts("baaaaaaaaaa"));
assertFalse(automaton.accepts("aaaaaaaaaaaaaaaxaaaaaa"));
assertFalse(automaton.accepts("bab"));
}
/**
* Test sprawdza metode Sum w AutomataOperations B.
*/
public final void testSumB() {
AutomatonSpecification automatonB = new NaiveAutomatonSpecification();
State q0B = automatonB.addState();
State q1B = automatonB.addState();
State q2B = automatonB.addState();
automatonB.addTransition(q0B, q1B, new CharTransitionLabel('a'));
automatonB.addTransition(q0B, q1B, new CharTransitionLabel('b'));
automatonB.addTransition(q1B, q2B, new CharTransitionLabel('a'));
automatonB.addTransition(q1B, q2B, new CharTransitionLabel('b'));
automatonB.markAsInitial(q0B);
automatonB.markAsFinal(q2B);
AutomatonSpecification automatonD = new NaiveAutomatonSpecification();
State q0D = automatonD.addState();
State q1D = automatonD.addState();
State q2D = automatonD.addState();
State q3D = automatonD.addState();
automatonD.addTransition(q0D, q1D, new CharTransitionLabel('a'));
automatonD.addTransition(q0D, q2D, new CharTransitionLabel('b'));
automatonD.addTransition(q1D, q3D, new CharTransitionLabel('a'));
automatonD.addTransition(q1D, q2D, new CharTransitionLabel('b'));
automatonD.addTransition(q2D, q0D, new CharTransitionLabel('c'));
automatonD.addTransition(q2D, q1D, new CharTransitionLabel('b'));
automatonD.addTransition(q2D, q3D, new CharTransitionLabel('a'));
automatonD.addTransition(q3D, q2D, new CharTransitionLabel('c'));
automatonD.addTransition(q3D, q0D, new CharTransitionLabel('b'));
automatonD.markAsInitial(q0D);
automatonD.markAsFinal(q3D);
AutomatonSpecification result = AutomataOperations.sum(automatonB, automatonD);
NondeterministicAutomatonByThompsonApproach automaton = new
NondeterministicAutomatonByThompsonApproach(result);
assertTrue(automaton.accepts("ab"));
assertTrue(automaton.accepts("abbabba"));
assertTrue(automaton.accepts("bbbcaacba"));
assertTrue(automaton.accepts("aacacaca"));
assertTrue(automaton.accepts("aa"));
assertFalse(automaton.accepts("zle"));
assertFalse(automaton.accepts("b"));
assertFalse(automaton.accepts(""));
assertFalse(automaton.accepts("aac"));
}
/**
* Test sprawdza metode Sum w AutomataOperations C.
*/
public final void testSumC() {
AutomatonSpecification automatonB = new NaiveAutomatonSpecification();
State q0B = automatonB.addState();
State q1B = automatonB.addState();
State q2B = automatonB.addState();
automatonB.addTransition(q0B, q1B, new CharTransitionLabel('a'));
automatonB.addTransition(q0B, q1B, new CharTransitionLabel('b'));
automatonB.addTransition(q1B, q2B, new CharTransitionLabel('a'));
automatonB.addTransition(q1B, q2B, new CharTransitionLabel('b'));
automatonB.markAsInitial(q0B);
automatonB.markAsFinal(q2B);
AutomatonSpecification automatonC = new NaiveAutomatonSpecification();
State q0C = automatonC.addState();
automatonC.addLoop(q0C, new CharTransitionLabel('a'));
automatonC.addLoop(q0C, new CharTransitionLabel('b'));
automatonC.addLoop(q0C, new CharTransitionLabel('c'));
automatonC.addLoop(q0C, new CharTransitionLabel('d'));
automatonC.markAsInitial(q0C);
automatonC.markAsFinal(q0C);
AutomatonSpecification result = AutomataOperations.sum(automatonB, automatonC);
NondeterministicAutomatonByThompsonApproach automaton = new
NondeterministicAutomatonByThompsonApproach(result);
assertTrue(automaton.accepts("babbaccddcaaccb"));
assertTrue(automaton.accepts("bbaccddbaba"));
assertTrue(automaton.accepts("bbbcaacba"));
assertTrue(automaton.accepts("aaaaaaaaaaaaaaaa"));
assertTrue(automaton.accepts(""));
assertFalse(automaton.accepts("bbaccddxbaba"));
assertFalse(automaton.accepts("czytwojprogrammackutozaakceptuje"));
assertFalse(automaton.accepts("zielonosmutnaniebieskowesolapomaranczowa"));
}
/**
* Test sprawdza metode Sum w AutomataOperations D.
*/
public final void testSumD() {
AutomatonSpecification automatonB = new NaiveAutomatonSpecification();
State q0B = automatonB.addState();
State q1B = automatonB.addState();
State q2B = automatonB.addState();
automatonB.addTransition(q0B, q1B, new CharTransitionLabel('a'));
automatonB.addTransition(q0B, q1B, new CharTransitionLabel('b'));
automatonB.addTransition(q1B, q2B, new CharTransitionLabel('a'));
automatonB.addTransition(q1B, q2B, new CharTransitionLabel('b'));
automatonB.markAsInitial(q0B);
automatonB.markAsFinal(q2B);
AutomatonSpecification automatonE = new NaiveAutomatonSpecification();
State q0E = automatonE.addState();
automatonE.addTransition(q0E, q0E, new EpsilonTransitionLabel());
automatonE.markAsInitial(q0E);
automatonE.markAsFinal(q0E);
AutomatonSpecification result = AutomataOperations.sum(automatonB, automatonE);
NondeterministicAutomatonByThompsonApproach automaton = new
NondeterministicAutomatonByThompsonApproach(result);
assertTrue(automaton.accepts(""));
assertTrue(automaton.accepts("aa"));
assertFalse(automaton.accepts("bbaccddxbaba"));
assertFalse(automaton.accepts("aabbbaaaa"));
}
/**
* Test sprawdza metode Sum w AutomataOperations E.
*/
public final void testSumE() {
AutomatonSpecification automatonB = new NaiveAutomatonSpecification();
State q0B = automatonB.addState();
State q1B = automatonB.addState();
State q2B = automatonB.addState();
automatonB.addTransition(q0B, q1B, new CharTransitionLabel('a'));
automatonB.addTransition(q0B, q1B, new CharTransitionLabel('b'));
automatonB.addTransition(q1B, q2B, new CharTransitionLabel('a'));
automatonB.addTransition(q1B, q2B, new CharTransitionLabel('b'));
automatonB.markAsInitial(q0B);
automatonB.markAsFinal(q2B);
AutomatonSpecification automatonF = new NaiveAutomatonSpecification();
State q0F = automatonF.addState();
State q1F = automatonF.addState();
State q2F = automatonF.addState();
State q3F = automatonF.addState();
State q7F = automatonF.addState();
State q5F = automatonF.addState();
State q6F = automatonF.addState();
automatonF.addTransition(q0F, q1F, new CharTransitionLabel('a'));
automatonF.addTransition(q0F, q3F, new EpsilonTransitionLabel());
automatonF.addTransition(q0F, q2F, new EpsilonTransitionLabel());
automatonF.addTransition(q3F, q7F, new CharTransitionLabel('a'));
automatonF.addTransition(q2F, q5F, new EpsilonTransitionLabel());
automatonF.addTransition(q5F, q6F, new CharTransitionLabel('b'));
automatonF.markAsInitial(q0F);
automatonF.markAsFinal(q1F);
automatonF.markAsFinal(q7F);
automatonF.markAsFinal(q6F);
AutomatonSpecification result = AutomataOperations.sum(automatonB, automatonF);
NondeterministicAutomatonByThompsonApproach automaton = new
NondeterministicAutomatonByThompsonApproach(result);
assertTrue(automaton.accepts("aa"));
assertTrue(automaton.accepts("b"));
assertTrue(automaton.accepts("a"));
assertFalse(automaton.accepts("aaabbbb"));
assertFalse(automaton.accepts(""));
}
/**
* Testuje automat akceptujący domknięcie Kleene'ego
* języka akceptowanego przez dany automat.
*/
public final void testGetKleeneStar() {
AutomatonSpecification automaton = new NaiveAutomatonSpecification();
State q0 = automaton.addState();
State q1 = automaton.addState();
State q2 = automaton.addState();
State q3 = automaton.addState();
State q4 = automaton.addState();
automaton.addTransition(q0, q1, new CharTransitionLabel('a'));
automaton.addTransition(q1, q2, new CharTransitionLabel('b'));
automaton.addTransition(q2, q3, new CharTransitionLabel('a'));
automaton.addTransition(q3, q4, new CharTransitionLabel('c'));
automaton.markAsInitial(q0);
automaton.markAsFinal(q4);
AutomatonSpecification result =
AutomataOperations.getKleeneStar(automaton);
NondeterministicAutomatonByThompsonApproach automatonKleeneStar = new
NondeterministicAutomatonByThompsonApproach(result);
assertTrue(automatonKleeneStar.accepts("abac"));
assertTrue(automatonKleeneStar.accepts("abacabacabacabacabacabac"));
assertTrue(automatonKleeneStar.accepts("abacabacabacabacabac"));
assertFalse(automatonKleeneStar.accepts("abacabacabacabbbbacabac"));
assertFalse(automatonKleeneStar.accepts("aba"));
assertFalse(automatonKleeneStar.accepts("bababc"));
}
/**
* Test funkcji determinize2(). Automat akceptuje słowa postaci:
* ((b)^2n)(a^m)(*), gdzie m,n >= 0, a (*) oznacza dowolny ciąg znaków.
*/
public final void testDeterminize2SimpleAutomaton() {
AutomatonSpecification nonDeterministicAutomat = new NaiveAutomatonSpecification();
DeterministicAutomatonSpecification deterministicAutomat
= new NaiveDeterministicAutomatonSpecification();
State qPoczatkowy = nonDeterministicAutomat.addState();
State qKoncowy = nonDeterministicAutomat.addState();
nonDeterministicAutomat.addLoop(qPoczatkowy, new CharTransitionLabel('a'));
nonDeterministicAutomat.addTransition(qPoczatkowy, qKoncowy, new CharTransitionLabel('a'));
nonDeterministicAutomat.addTransition(qPoczatkowy, qKoncowy, new CharTransitionLabel('b'));
nonDeterministicAutomat.addTransition(qKoncowy, qPoczatkowy, new CharTransitionLabel('b'));
nonDeterministicAutomat.markAsFinal(qPoczatkowy);
nonDeterministicAutomat.markAsInitial(qPoczatkowy);
try {
AutomataOperations.determinize2(nonDeterministicAutomat, deterministicAutomat);
} catch (Exception e) {
fail();
}
AutomatonByRecursion zdeterminizowany = new AutomatonByRecursion(deterministicAutomat);
assertTrue(zdeterminizowany.accepts(""));
assertTrue(zdeterminizowany.accepts("aaaaa"));
assertTrue(zdeterminizowany.accepts("abbababbaa"));
assertTrue(zdeterminizowany.accepts("bbaba"));
assertFalse(zdeterminizowany.accepts("bababb"));
}
/**
* Test funkcji determinize2(). Prosty automat niedeterministyczny z Wikipedii.
*/
public final void testDeterminize2AutomatonFromWikipedia() {
AutomatonSpecification nonDeterministicAutomat = new NaiveAutomatonSpecification();
DeterministicAutomatonSpecification innaNazwa
= new NaiveDeterministicAutomatonSpecification();
State qA = nonDeterministicAutomat.addState();
State qB = nonDeterministicAutomat.addTransition(qA, new CharTransitionLabel('1'));
State qC = nonDeterministicAutomat.addTransition(qA, new CharTransitionLabel('1'));
nonDeterministicAutomat.addTransition(qC, qB, new CharTransitionLabel('0'));
nonDeterministicAutomat.addTransition(qB, qA, new CharTransitionLabel('0'));
nonDeterministicAutomat.markAsInitial(qA);
nonDeterministicAutomat.markAsFinal(qC);
try {
AutomataOperations.determinize2(nonDeterministicAutomat, innaNazwa);
} catch (Exception e) {
fail();
}
AutomatonByRecursion zdeterminizowany = new AutomatonByRecursion(innaNazwa);
assertFalse(zdeterminizowany.accepts(""));
assertTrue(zdeterminizowany.accepts("1"));
assertTrue(zdeterminizowany.accepts("101"));
assertTrue(zdeterminizowany.accepts("10101001"));
assertFalse(zdeterminizowany.accepts("1000"));
assertFalse(zdeterminizowany.accepts("0"));
}
/**
* Test funkcji determinize2(). Automat !już! deterministyczny akceptuje tylko słowa:
* Marcin, Maria, Marianna, Mariusz, Marek, Marzena.
*/
public final void testDeterminize2DeterministicSixNames() {
AutomatonSpecification nonDeterministicAutomat = new NaiveAutomatonSpecification();
DeterministicAutomatonSpecification deterministicAutomat
= new NaiveDeterministicAutomatonSpecification();
State qPoczatkowy = nonDeterministicAutomat.addState();
State qMar = nonDeterministicAutomat.addTransitionSequence(qPoczatkowy, "Mar");
State qMarc = nonDeterministicAutomat.addTransition(qMar, new CharTransitionLabel('c'));
State qMarcin = nonDeterministicAutomat.addTransitionSequence(qMarc, "in");
State qMari = nonDeterministicAutomat.addTransition(qMar, new CharTransitionLabel('i'));
State qMaria = nonDeterministicAutomat.addTransition(qMari, new CharTransitionLabel('a'));
State qMarianna = nonDeterministicAutomat.addTransitionSequence(qMaria, "nna");
State qMariusz = nonDeterministicAutomat.addTransitionSequence(qMari, "usz");
State qMarek = nonDeterministicAutomat.addTransitionSequence(qMar, "ek");
State qMarzena = nonDeterministicAutomat.addTransitionSequence(qMar, "zena");
nonDeterministicAutomat.markAsInitial(qPoczatkowy);
nonDeterministicAutomat.markAsFinal(qMarcin);
nonDeterministicAutomat.markAsFinal(qMaria);
nonDeterministicAutomat.markAsFinal(qMarianna);
nonDeterministicAutomat.markAsFinal(qMariusz);
nonDeterministicAutomat.markAsFinal(qMarek);
nonDeterministicAutomat.markAsFinal(qMarzena);
try {
AutomataOperations.determinize2(nonDeterministicAutomat, deterministicAutomat);
} catch (Exception e) {
fail();
}
AutomatonByRecursion zdeterminizowany = new AutomatonByRecursion(deterministicAutomat);
assertFalse(zdeterminizowany.accepts(""));
assertTrue(zdeterminizowany.accepts("Marcin"));
assertTrue(zdeterminizowany.accepts("Maria"));
assertTrue(zdeterminizowany.accepts("Marianna"));
assertTrue(zdeterminizowany.accepts("Mariusz"));
assertTrue(zdeterminizowany.accepts("Marek"));
assertTrue(zdeterminizowany.accepts("Marzena"));
assertFalse(zdeterminizowany.accepts("mariusz"));
}
/**
* Test funkcji determinize2(). Automaty są niepoprawne dla tej metody, powinna ona
* zwracać wyjątki.
*/
public final void testDeterminize2WrongAutomatons() {
AutomatonSpecification nonDeterministicAutomat = new NaiveAutomatonSpecification();
DeterministicAutomatonSpecification deterministicAutomat
= new NaiveDeterministicAutomatonSpecification();
try {
AutomataOperations.determinize2(nonDeterministicAutomat, deterministicAutomat);
} catch (Exception e) {
assertTrue(true);
}
State first = nonDeterministicAutomat.addState();
nonDeterministicAutomat.addTransition(first, new EpsilonTransitionLabel());
try {
AutomataOperations.determinize2(nonDeterministicAutomat, deterministicAutomat);
} catch (Exception e) {
assertTrue(true);
}
}
/**
* Test funkcji determinize2(). Automat zawiera ComplementCharClassTransitionLabel.
*/
public final void testDeterminize2AutomatonWithComplementCharClass() {
AutomatonSpecification nonDeterministicAutomat = new NaiveAutomatonSpecification();
DeterministicAutomatonSpecification deterministicAutomat
= new NaiveDeterministicAutomatonSpecification();
State qBegin = nonDeterministicAutomat.addState();
State qFirstEnd = nonDeterministicAutomat
.addTransition(qBegin, new ComplementCharClassTransitionLabel("a-gt"));
State qSecondEnd = nonDeterministicAutomat
.addTransition(qBegin, new CharTransitionLabel('z'));
State qThirdArm = nonDeterministicAutomat
.addTransition(qBegin, new ComplementCharClassTransitionLabel("f-t"));
State qThirdEnd = nonDeterministicAutomat
.addTransition(qThirdArm, new CharTransitionLabel('z'));
nonDeterministicAutomat.markAsInitial(qBegin);
nonDeterministicAutomat.markAsFinal(qFirstEnd);
nonDeterministicAutomat.markAsFinal(qSecondEnd);
nonDeterministicAutomat.markAsFinal(qThirdEnd);
try {
AutomataOperations.determinize2(nonDeterministicAutomat, deterministicAutomat);
} catch (Exception e) {
fail();
}
AutomatonByRecursion zdeterminizowany = new AutomatonByRecursion(deterministicAutomat);
assertFalse(zdeterminizowany.accepts(""));
assertTrue(zdeterminizowany.accepts("z"));
assertTrue(zdeterminizowany.accepts("ez"));
assertTrue(zdeterminizowany.accepts("uz"));
assertTrue(zdeterminizowany.accepts("h"));
assertTrue(zdeterminizowany.accepts("k"));
assertFalse(zdeterminizowany.accepts("f"));
}
/**
* Test funkcji determinize2(). Automat zawiera CharSetTransitionLabel.
*/
public final void testDeterminize2AutomatonWithCharSet() {
AutomatonSpecification nonDeterministicAutomat = new NaiveAutomatonSpecification();
DeterministicAutomatonSpecification deterministicAutomat
= new NaiveDeterministicAutomatonSpecification();
State qBegin = nonDeterministicAutomat.addState();
State qFirstArm = nonDeterministicAutomat
.addTransition(qBegin, new CharTransitionLabel('a'));
State qFirstEnd = nonDeterministicAutomat
.addTransition(qFirstArm, new AnyTransitionLabel());
HashSet<Character> mySet = new HashSet<Character>();
mySet.add('b');
mySet.add('d');
mySet.add('z');
State qSecondEnd = nonDeterministicAutomat
.addTransition(qFirstArm, new CharSetTransitionLabel(mySet));
HashSet<Character> mySet2 = new HashSet<Character>();
mySet2.add('b');
mySet2.add('d');
mySet2.add('z');
mySet2.add('a');
mySet2.add('f');
mySet2.add('h');
nonDeterministicAutomat.addTransition(qBegin, qSecondEnd,
new CharSetTransitionLabel(mySet2));
HashSet<Character> mySet3 = new HashSet<Character>();
mySet3.add('a');
mySet3.add('f');
mySet3.add('h');
nonDeterministicAutomat.addTransition(qSecondEnd, qFirstEnd,
new CharSetTransitionLabel(mySet3));
nonDeterministicAutomat.markAsInitial(qBegin);
nonDeterministicAutomat.markAsFinal(qFirstEnd);
nonDeterministicAutomat.markAsFinal(qSecondEnd);
try {
AutomataOperations.determinize2(nonDeterministicAutomat, deterministicAutomat);
} catch (Exception e) {
fail();
}
AutomatonByRecursion zdeterminizowany = new AutomatonByRecursion(deterministicAutomat);
assertFalse(zdeterminizowany.accepts(""));
assertTrue(zdeterminizowany.accepts("a"));
assertTrue(zdeterminizowany.accepts("b"));
assertTrue(zdeterminizowany.accepts("h"));
assertTrue(zdeterminizowany.accepts("z"));
assertTrue(zdeterminizowany.accepts("az"));
assertTrue(zdeterminizowany.accepts("ak"));
assertTrue(zdeterminizowany.accepts("bf"));
assertTrue(zdeterminizowany.accepts("zh"));
assertFalse(zdeterminizowany.accepts("g"));
assertFalse(zdeterminizowany.accepts("A"));
assertFalse(zdeterminizowany.accepts("fz"));
assertFalse(zdeterminizowany.accepts("c"));
}
/**
* Test funkcji determinize2(). Automat zawiera CharRangeTransitionLabel.
*/
public final void testDeterminize2AutomatonWithCharRange() {
AutomatonSpecification nonDeterministicAutomat = new NaiveAutomatonSpecification();
DeterministicAutomatonSpecification deterministicAutomat
= new NaiveDeterministicAutomatonSpecification();
State qBegin = nonDeterministicAutomat.addState();
State qFirstEnd = nonDeterministicAutomat
.addTransition(qBegin, new CharRangeTransitionLabel('a', 'f'));
State qSecondArm = nonDeterministicAutomat
.addTransition(qBegin, new CharTransitionLabel('a'));
State qSecondEnd = nonDeterministicAutomat
.addTransition(qSecondArm, new CharRangeTransitionLabel('g', 'j'));
nonDeterministicAutomat.addLoop(qFirstEnd, new CharTransitionLabel('a'));
nonDeterministicAutomat.markAsInitial(qBegin);
nonDeterministicAutomat.markAsFinal(qFirstEnd);
nonDeterministicAutomat.markAsFinal(qSecondEnd);
try {
AutomataOperations.determinize2(nonDeterministicAutomat, deterministicAutomat);
} catch (Exception e) {
fail();
}
AutomatonByRecursion zdeterminizowany = new AutomatonByRecursion(deterministicAutomat);
assertFalse(zdeterminizowany.accepts(""));
assertTrue(zdeterminizowany.accepts("a"));
assertTrue(zdeterminizowany.accepts("b"));
assertTrue(zdeterminizowany.accepts("c"));
assertTrue(zdeterminizowany.accepts("d"));
assertTrue(zdeterminizowany.accepts("e"));
assertTrue(zdeterminizowany.accepts("f"));
assertTrue(zdeterminizowany.accepts("aa"));
assertTrue(zdeterminizowany.accepts("fa"));
assertTrue(zdeterminizowany.accepts("ba"));
assertTrue(zdeterminizowany.accepts("ag"));
assertTrue(zdeterminizowany.accepts("aj"));
assertFalse(zdeterminizowany.accepts("g"));
assertFalse(zdeterminizowany.accepts("bb"));
assertFalse(zdeterminizowany.accepts("fat"));
}
/**
* Test funkcji determinize2(). Automat zawiera CharRangeTransitionLabel.
*/
public final void testDeterminize2BigAutomaton() {
AutomatonSpecification nonDeterministicAutomat = new NaiveAutomatonSpecification();
DeterministicAutomatonSpecification deterministicAutomat
= new NaiveDeterministicAutomatonSpecification();
State qBegin = nonDeterministicAutomat.addState();
nonDeterministicAutomat
.addTransition(qBegin, qBegin, new CharTransitionLabel('a'));
State q1 = nonDeterministicAutomat
.addTransition(qBegin, new CharTransitionLabel('a'));
State q2 = nonDeterministicAutomat
.addTransition(qBegin, new CharTransitionLabel('b'));
State q4 = nonDeterministicAutomat
.addTransition(qBegin, new CharTransitionLabel('a'));
nonDeterministicAutomat
.addTransition(q1, q2, new CharTransitionLabel('b'));
nonDeterministicAutomat
.addTransition(q2, q2, new CharTransitionLabel('b'));
State q3 = nonDeterministicAutomat
.addTransition(q2, new CharTransitionLabel('a'));
nonDeterministicAutomat
.addTransition(q3, q4, new CharTransitionLabel('b'));
State q5 = nonDeterministicAutomat
.addTransition(q4, new CharTransitionLabel('b'));
nonDeterministicAutomat
.addTransition(q5, q3, new CharTransitionLabel('a'));
nonDeterministicAutomat.markAsInitial(qBegin);
nonDeterministicAutomat.markAsFinal(q5);
try {
AutomataOperations.determinize2(nonDeterministicAutomat, deterministicAutomat);
} catch (Exception e) {
fail();
}
AutomatonByRecursion zdeterminizowany = new AutomatonByRecursion(deterministicAutomat);
assertFalse(zdeterminizowany.accepts(""));
assertTrue(zdeterminizowany.accepts("aaaab"));
assertTrue(zdeterminizowany.accepts("babb"));
assertTrue(zdeterminizowany.accepts("abbbbabb"));
assertFalse(zdeterminizowany.accepts("bbb"));
assertFalse(zdeterminizowany.accepts("aaa"));
assertFalse(zdeterminizowany.accepts("inne"));
}
/**
* Test metody Intersection z AutomataOperations na automatach z petlami.
*/
public final void testIntersectionSimple() {
AutomatonSpecification automatonA = new NaiveAutomatonSpecification();
State q0 = automatonA.addState();
State q1 = automatonA.addState();
automatonA.addTransition(q0, q1, new CharTransitionLabel('a'));
automatonA.addLoop(q1, new CharTransitionLabel('a'));
automatonA.addLoop(q1, new CharTransitionLabel('b'));
automatonA.markAsInitial(q0);
automatonA.markAsFinal(q1);
AutomatonSpecification automatonB = new NaiveAutomatonSpecification();
State q10 = automatonB.addState();
State q11 = automatonB.addState();
State q12 = automatonB.addState();
automatonB.addTransition(q10, q11, new CharTransitionLabel('a'));
automatonB.addTransition(q10, q11, new CharTransitionLabel('b'));
automatonB.addTransition(q11, q12, new CharTransitionLabel('a'));
automatonB.addTransition(q11, q12, new CharTransitionLabel('b'));
automatonB.markAsInitial(q10);
automatonB.markAsFinal(q12);
AutomatonSpecification result = AutomataOperations.intersection(automatonA, automatonB);
AutomatonByRecursion automaton = new AutomatonByRecursion(result);
assertTrue(automaton.accepts("aa"));
assertTrue(automaton.accepts("ab"));
assertFalse(automaton.accepts(""));
assertFalse(automaton.accepts("a"));
assertFalse(automaton.accepts("Blablablabla bla"));
assertFalse(automaton.accepts("abababab"));
assertFalse(automaton.accepts("aba"));
assertFalse(automaton.accepts("ba"));
}
/**
* Test metody intersection z AutomataOperations na automacie A z soba samym.
*/
public final void testIntersectionWithTheSameAutomaton() {
AutomatonSpecification automatonA = new NaiveAutomatonSpecification();
State q0 = automatonA.addState();
State q1 = automatonA.addState();
State q2 = automatonA.addState();
automatonA.addTransition(q0, q2, new CharTransitionLabel('b'));
automatonA.addTransition(q0, q1, new CharTransitionLabel('a'));
automatonA.addTransition(q1, q2, new CharTransitionLabel('a'));
automatonA.addLoop(q2, new CharTransitionLabel('b'));
automatonA.markAsInitial(q0);
automatonA.markAsFinal(q2);
AutomatonSpecification result = AutomataOperations.intersection(automatonA, automatonA);
AutomatonByRecursion automaton = new AutomatonByRecursion(result);
assertTrue(automaton.accepts("aabb"));
assertTrue(automaton.accepts("bb"));
assertTrue(automaton.accepts("bbbbbbbbbbbbbbbbb"));
assertFalse(automaton.accepts("aaaaaaaaaaaaaaaa"));
assertFalse(automaton.accepts("xxxxaabbxxxxxx"));
assertFalse(automaton.accepts(""));
}
/**
* Test metody intersection z AutomataOperations na automatach z epsilon przejsciami.
*/
public final void testIntersectionwithEpsilonTransition() {
AutomatonSpecification automatonA = new NotNaiveAutomatonSpecification();
State q0 = automatonA.addState();
State q1 = automatonA.addState();
State q2 = automatonA.addState();
automatonA.addTransition(q0, q1, new EpsilonTransitionLabel());
automatonA.addTransition(q0, q2, new EpsilonTransitionLabel());
automatonA.addLoop(q1, new CharTransitionLabel('a'));
automatonA.addLoop(q2, new CharTransitionLabel('b'));
automatonA.markAsInitial(q0);
automatonA.markAsFinal(q0);
automatonA.markAsFinal(q1);
automatonA.markAsFinal(q2);
AutomatonSpecification automatonB = new NotNaiveAutomatonSpecification();
State q10 = automatonB.addState();
State q11 = automatonB.addState();
State q12 = automatonB.addState();
State q13 = automatonB.addState();
State q14 = automatonB.addState();
State q15 = automatonB.addState();
State q16 = automatonB.addState();
automatonB.addTransition(q10, q11, new EpsilonTransitionLabel());
automatonB.addTransition(q10, q14, new EpsilonTransitionLabel());
automatonB.addTransition(q11, q12, new CharTransitionLabel('a'));
automatonB.addTransition(q12, q13, new CharTransitionLabel('b'));
automatonB.addLoop(q13, new CharTransitionLabel('b'));
automatonB.addTransition(q14, q15, new CharTransitionLabel('b'));
automatonB.addTransition(q15, q16, new CharTransitionLabel('b'));
automatonB.addLoop(q16, new CharTransitionLabel('b'));
automatonB.markAsInitial(q10);
automatonB.markAsFinal(q12);
automatonB.markAsFinal(q13);
automatonB.markAsFinal(q15);
AutomatonSpecification result = AutomataOperations.intersection(automatonA, automatonB);
NondeterministicAutomatonByThompsonApproach automaton = new
NondeterministicAutomatonByThompsonApproach(result);
assertTrue(automaton.accepts("b"));
assertTrue(automaton.accepts("a"));
assertFalse(automaton.accepts("aaaaaaaaaaaaaaaa"));
assertFalse(automaton.accepts("bbbbbbbbbbbbbbbbbb"));
assertFalse(automaton.accepts(""));
assertFalse(automaton.accepts("abbb"));
assertFalse(automaton.accepts("nieakceptowanedlugieslowo"));
}
/**
* Test metody intersection z AutomataOperations gdzie automat A
* ma epsilon przejscia i stan koncowy jest poczatkowym.
*/
public final void testIntersectionwhereInitialIsFinalA() {
AutomatonSpecification automatonA = new NaiveAutomatonSpecification();
State q0 = automatonA.addState();
automatonA.addLoop(q0, new CharTransitionLabel('b'));
automatonA.markAsInitial(q0);
automatonA.markAsFinal(q0);
AutomatonSpecification automatonB = new NaiveAutomatonSpecification();
State q10 = automatonB.addState();
State q11 = automatonB.addState();
automatonB.addTransition(q10, q11, new CharTransitionLabel('b'));
automatonB.addTransition(q10, q11, new EpsilonTransitionLabel());
automatonB.markAsInitial(q10);
automatonB.markAsFinal(q10);
automatonB.markAsFinal(q11);
AutomatonSpecification result = AutomataOperations.intersection(automatonA, automatonB);
NondeterministicAutomatonByThompsonApproach automaton = new
NondeterministicAutomatonByThompsonApproach(result);
assertTrue(automaton.accepts("b"));
assertTrue(automaton.accepts(""));
assertFalse(automaton.accepts("a"));
assertFalse(automaton.accepts("bbbbbbbbbbbbbb"));
assertFalse(automaton.accepts("bardzodlugieslowowbardzodlugieslowo"));
}
/**
* Test metody intersection z AutomataOperations gdzie automat B
* ma epsilon przejscia i stan koncowy jest poczatkowym.
*/
public final void testIntersectionwhereInitialisFinalB() {
AutomatonSpecification automatonA = new NaiveAutomatonSpecification();
State q10 = automatonA.addState();
State q11 = automatonA.addState();
automatonA.addTransition(q10, q11, new CharTransitionLabel('b'));
automatonA.addTransition(q10, q11, new EpsilonTransitionLabel());
automatonA.markAsInitial(q10);
automatonA.markAsFinal(q10);
automatonA.markAsFinal(q11);
AutomatonSpecification automatonB = new NaiveAutomatonSpecification();
State q0 = automatonB.addState();
automatonB.addLoop(q0, new CharTransitionLabel('b'));
automatonB.markAsInitial(q0);
automatonB.markAsFinal(q0);
AutomatonSpecification result = AutomataOperations.intersection(automatonA, automatonB);
NondeterministicAutomatonByThompsonApproach automaton = new
NondeterministicAutomatonByThompsonApproach(result);
assertTrue(automaton.accepts("b"));
assertTrue(automaton.accepts(""));
assertFalse(automaton.accepts("a"));
assertFalse(automaton.accepts("bbbbbbbbbbbbbb"));
assertFalse(automaton.accepts("bardzodlugieslowowbardzodlugieslowo"));
}
/**
* Test metody intersection na automacie bez stanu końcowego.
*/
public final void testIntersectionOnNoFiniteStateAutomaton() {
AutomatonSpecification automatonA =
new NaiveAutomatonSpecification().makeOneTransitionAutomaton('a');
AutomatonSpecification automatonB = new NaiveAutomatonSpecification();
State q0 = automatonB.addState();
automatonB.markAsInitial(q0);
automatonB.addTransition(q0, new CharTransitionLabel('a'));
AutomatonSpecification intersectedAB = AutomataOperations.intersection(
automatonA, automatonB);
NondeterministicAutomatonByThompsonApproach automatonAB = new
NondeterministicAutomatonByThompsonApproach(intersectedAB);
assertFalse(automatonAB.accepts("a"));
assertFalse(automatonAB.accepts(""));
}
/**
* Test complementLanguageAutomaton() dla automatu "pustego".
*/
public final void testComplementLanguageAutomaton0EmptyAutomaton() {
DeterministicAutomatonSpecification pustyOjciec = new
NaiveDeterministicAutomatonSpecification();
State q0 = pustyOjciec.addState();
pustyOjciec.addLoop(q0, new CharTransitionLabel('a'));
pustyOjciec.markAsInitial(q0);
HashSet<Character> zbior = new HashSet<Character>();
zbior.add('a');
zbior.add('b');
zbior.add('c');
AutomatonByRecursion pusteDziecko = new
AutomatonByRecursion(AutomataOperations.complementLanguageAutomaton(pustyOjciec, zbior));
assertTrue(pusteDziecko.accepts("a"));
assertTrue(pusteDziecko.accepts("abba"));
assertTrue(pusteDziecko.accepts(""));
assertTrue(pusteDziecko.accepts("cc"));
assertFalse(pusteDziecko.accepts("dd"));
}
/**
* Test complementLanguageAutomaton() dla automatu akceptującego dziwne "a".
*/
public final void testComplementLanguageAutomaton1StrangeAAutomaton() {
DeterministicAutomatonSpecification autLucas = new
NaiveDeterministicAutomatonSpecification();
State q0 = autLucas.addState();
State q1 = autLucas.addState();
State q2 = autLucas.addState();
State q3 = autLucas.addState();
autLucas.addTransition(q0, q1, new CharTransitionLabel('a'));
autLucas.addTransition(q1, q2, new CharTransitionLabel('a'));
autLucas.addTransition(q2, q3, new CharTransitionLabel('a'));
autLucas.addTransition(q3, q1, new CharTransitionLabel('a'));
autLucas.markAsInitial(q0);
autLucas.markAsFinal(q2);
autLucas.markAsFinal(q3);
HashSet<Character> zbior = new HashSet<Character>();
zbior.add('a');
AutomatonByRecursion autLucasBR = new
AutomatonByRecursion(AutomataOperations.complementLanguageAutomaton(autLucas, zbior));
assertTrue(autLucasBR.accepts(""));
assertTrue(autLucasBR.accepts("a"));
assertTrue(autLucasBR.accepts("aaaa"));
assertFalse(autLucasBR.accepts("aa"));
assertFalse(autLucasBR.accepts("aaa"));
}
/**
* Test complementLanguageAutomaton() dla automatu akceptującego "ab" i "ba".
*/
public final void testComplementLanguageAutomaton2AbBaAutomaton() {
DeterministicAutomatonSpecification abba = new NaiveDeterministicAutomatonSpecification();
State q0 = abba.addState();
State qa = abba.addTransition(q0, new CharTransitionLabel('a'));
State qb = abba.addTransition(q0, new CharTransitionLabel('b'));
State qab = abba.addTransition(qa, new CharTransitionLabel('b'));
State qba = abba.addTransition(qb, new CharTransitionLabel('a'));
State smietnik = abba.addTransition(qa, new CharTransitionLabel('a'));
abba.addTransition(qb, smietnik, new CharTransitionLabel('b'));
abba.addTransition(qab, smietnik, new CharTransitionLabel('a'));
abba.addTransition(qab, smietnik, new CharTransitionLabel('b'));
abba.addTransition(qba, smietnik, new CharTransitionLabel('a'));
abba.addTransition(qba, smietnik, new CharTransitionLabel('b'));
abba.addLoop(smietnik, new CharTransitionLabel('a'));
abba.addLoop(smietnik, new CharTransitionLabel('b'));
abba.markAsInitial(q0);
abba.markAsFinal(qab);
abba.markAsFinal(qba);
HashSet<Character> zbior = new HashSet<Character>();
zbior.add('a');
zbior.add('b');
AutomatonByRecursion abbaBR = new
AutomatonByRecursion(AutomataOperations.complementLanguageAutomaton(abba, zbior));
assertTrue(abbaBR.accepts(""));
assertTrue(abbaBR.accepts("a"));
assertTrue(abbaBR.accepts("b"));
assertFalse(abbaBR.accepts("ab"));
assertFalse(abbaBR.accepts("ba"));
assertTrue(abbaBR.accepts("aa"));
assertTrue(abbaBR.accepts("bb"));
assertTrue(abbaBR.accepts("aba"));
assertTrue(abbaBR.accepts("bab"));
assertTrue(abbaBR.accepts("abb"));
assertTrue(abbaBR.accepts("baa"));
}
/**
* Test metody determinize2 na prostym automacie z pokrywającym
* się etykietami przejść.
*/
public final void testDeterminize2OverlappingLabels() {
AutomatonSpecification spec = new NaiveAutomatonSpecification();
State q0 = spec.addState();
State q1 = spec.addState();
State q2 = spec.addState();
State q3 = spec.addState();
State q4 = spec.addState();
spec.markAsInitial(q0);
spec.markAsFinal(q3);
spec.markAsFinal(q4);
spec.addTransition(q0, q1, new CharRangeTransitionLabel('a', 'b'));
spec.addTransition(q0, q2, new CharRangeTransitionLabel('b', 'c'));
spec.addTransition(q1, q3, new CharTransitionLabel('x'));
spec.addTransition(q2, q4, new CharTransitionLabel('y'));
AutomatonByStack automaton = new AutomatonByStack(spec);
helperForDeterminize2OverlappingLabels(automaton);
DeterministicAutomatonSpecification dspec = new NaiveDeterministicAutomatonSpecification();
try {
AutomataOperations.determinize2(spec, dspec);
} catch (StructureException exception) {
exception.printStackTrace();
throw new RuntimeException(exception);
}
DeterministicAutomaton dautomaton = new DeterministicAutomaton(dspec);
helperForDeterminize2OverlappingLabels(dautomaton);
}
private void helperForDeterminize2OverlappingLabels(Acceptor acceptor) {
assertTrue(acceptor.accepts("ax"));
assertTrue(acceptor.accepts("bx"));
assertTrue(acceptor.accepts("by"));
assertTrue(acceptor.accepts("cy"));
assertFalse(acceptor.accepts("ay"));
assertFalse(acceptor.accepts("cx"));
}
/**
* Test sprawdza, czy odwracanie automatu działa.
*/
public final void testInversionA() {
List<String> words = new ArrayList<String>();
words.add("ab");
words.add("ba");
words.add("caa");
words.add("bbba");
words.add("bbb");
words.add("bab");
words.add("abb");
words.add("aaa");
words.add("a");
words.add("b");
words.add("");
NaiveAutomatonSpecification automatonA = new NaiveAutomatonSpecification();
State q0 = automatonA.addState();
State q1 = automatonA.addState();
automatonA.addTransition(q0, q1, new CharTransitionLabel('a'));
automatonA.addLoop(q1, new CharTransitionLabel('a'));
automatonA.addLoop(q1, new CharTransitionLabel('b'));
automatonA.markAsInitial(q0);
automatonA.markAsFinal(q1);
AutomatonSpecification automatonB = AutomataOperations.reverseLanguageAutomaton(automatonA);
NondeterministicAutomatonByThompsonApproach originalAutomaton = new
NondeterministicAutomatonByThompsonApproach(automatonA);
NondeterministicAutomatonByThompsonApproach reversedAutomaton = new
NondeterministicAutomatonByThompsonApproach(automatonB);
List<String> wordsToAccept = new ArrayList<String>();
List<String> wordsToReject = new ArrayList<String>();
for (String word : words) {
String reversedWord = new StringBuffer(word).reverse().toString();
if (originalAutomaton.accepts(word))
wordsToAccept.add(reversedWord);
else
wordsToReject.add(reversedWord);
}
for (String word : wordsToAccept) {
assertTrue(reversedAutomaton.accepts(word));
}
for (String word : wordsToReject) {
assertFalse(reversedAutomaton.accepts(word));
}
}
/**
* Test sprawdza, czy odwracanie automatu działa (B).
*/
public final void testInversionB() {
List<String> words = new ArrayList<String>();
words.add("cb");
words.add("bc");
words.add("bab");
words.add("bac");
words.add("cba");
words.add("cbb");
words.add("aaa");
words.add("aab");
words.add("aac");
words.add("aba");
words.add("abb");
words.add("abc");
words.add("aca");
words.add("acb");
words.add("acc");
words.add("aa");
words.add("ab");
words.add("ac");
words.add("ba");
words.add("bb");
words.add("bc");
words.add("ca");
words.add("cb");
words.add("cc");
words.add("a");
words.add("b");
words.add("c");
words.add("");
words.add("cb");
words.add("cab");
words.add("caab");
words.add("bc");
words.add("bac");
words.add("baac");
words.add("aac");
words.add("aab");
words.add("caa");
words.add("baa");
NaiveAutomatonSpecification automatonA = new NaiveAutomatonSpecification();
State q0 = automatonA.addState();
State q1 = automatonA.addState();
State q2 = automatonA.addState();
State q3 = automatonA.addState();
automatonA.addTransition(q0, q1, new CharTransitionLabel('c'));
automatonA.addTransition(q1, q2, new CharTransitionLabel('a'));
automatonA.addLoop(q2, new CharTransitionLabel('a'));
automatonA.addTransition(q2, q3, new CharTransitionLabel('b'));
automatonA.markAsInitial(q0);
automatonA.markAsFinal(q3);
AutomatonSpecification automatonB = AutomataOperations.reverseLanguageAutomaton(automatonA);
NondeterministicAutomatonByThompsonApproach originalAutomaton = new
NondeterministicAutomatonByThompsonApproach(automatonA);
NondeterministicAutomatonByThompsonApproach reversedAutomaton = new
NondeterministicAutomatonByThompsonApproach(automatonB);
List<String> wordsToAccept = new ArrayList<String>();
List<String> wordsToReject = new ArrayList<String>();
for (String word : words) {
String reversedWord = new StringBuffer(word).reverse().toString();
if (originalAutomaton.accepts(word))
wordsToAccept.add(reversedWord);
else
wordsToReject.add(reversedWord);
}
for (String word : wordsToAccept) {
assertTrue(reversedAutomaton.accepts(word));
}
for (String word : wordsToReject) {
assertFalse(reversedAutomaton.accepts(word));
}
}
}