package pl.edu.amu.wmi.daut.base;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
/**
* Klasa do determinizacji NFA.
*/
public class Determinizer {
/**
* Lista zbiorow stanow.
*/
private List<StateSet> listOfSets = new LinkedList<StateSet>();
/**
* Porownanie dwoch TransitioLabel; aktualnie prymitywne, bo moze byc tylko CharTransitionLabel.
* @return
* Jeden z argumentow jesli przechodza po tym samym lub EmptyTransitionLabel.
*/
private TransitionLabel equalTrLabel(TransitionLabel trA, TransitionLabel trB) {
if (trA != trB) {
return trA.intersect(trB);
}
return trA;
}
private boolean addTrToSet(TransitionLabel thisLabel, Set<TransitionLabel> addHere) {
boolean exists = false;
for (TransitionLabel temp : addHere) {
if (!equalTrLabel(thisLabel, temp).isEmpty()) {
exists = true;
break;
}
}
if (!exists) {
return addHere.add(thisLabel);
}
return false;
}
/**
* Sprawdza, czy zbior sS juz istnieje i zwraca ten zbior; null jesli nie istnieje.
*/
private StateSet existsSet(StateSet sS) {
for (StateSet tmpSS : listOfSets) {
if (tmpSS.isEqual(sS)) {
return tmpSS;
}
}
return null;
}
/**
* Dla nieterministycznego automatu skończenie stanowego nfa
* tworzy równoważny automat deterministyczny.
* Automat deterministyczny będzie tworzony poprzez rozbudowywanie
* pustego automatu emptyDfa.
*/
public void determinize(AutomatonSpecification nfa,
DeterministicAutomatonSpecification emptyDfa) {
if (!nfa.isEmpty() && emptyDfa.isEmpty()) {
if (nfa.isDeterministic()) {
State initialState = emptyDfa.addState();
emptyDfa.markAsInitial(initialState);
emptyDfa.insert(initialState, nfa);
} else {
Queue<StateSet> queueOfNewSets = new LinkedList<StateSet>();
StateSet initialSet = new StateSet(nfa.getInitialState());
initialSet.setThatState(emptyDfa.addState());
emptyDfa.markAsInitial(initialSet.getThatState());
if (nfa.isFinal(nfa.getInitialState())) {
emptyDfa.markAsFinal(initialSet.getThatState());
}
listOfSets.add(initialSet);
queueOfNewSets.offer(initialSet);
StateSet currentStSet;
while ((currentStSet = queueOfNewSets.poll()) != null) {
Set<TransitionLabel> setsTrLabels = new HashSet<TransitionLabel>();
for (State tmpSt : currentStSet.getStateSet()) {
for (OutgoingTransition tmpOuTra : nfa.allOutgoingTransitions(tmpSt)) {
addTrToSet(tmpOuTra.getTransitionLabel(), setsTrLabels);
}
}
for (TransitionLabel currentTrLabel : setsTrLabels) {
StateSet newStSet = new StateSet();
for (State tmpState : currentStSet.getStateSet()) {
for (OutgoingTransition tmpOuTr
: nfa.allOutgoingTransitions(tmpState)) {
if (!equalTrLabel(currentTrLabel,
tmpOuTr.getTransitionLabel()).isEmpty()) {
newStSet.add(tmpOuTr.getTargetState());
}
}
}
StateSet foundStSet = existsSet(newStSet);
if (foundStSet != null) {
newStSet = foundStSet;
} else {
listOfSets.add(newStSet);
queueOfNewSets.offer(newStSet);
newStSet.setThatState(emptyDfa.addState());
for (State finalState : newStSet.getStateSet()) {
if (nfa.isFinal(finalState)) {
emptyDfa.markAsFinal(newStSet.getThatState());
break;
}
}
}
emptyDfa.addTransition(currentStSet.getThatState(), newStSet.getThatState(),
currentTrLabel);
}
}
}
}
}
}