use of org.eclipse.collections.impl.map.mutable.primitive.CharObjectHashMap in project narchy by automenta.
the class DFA method minimize.
private int[][] minimize(Map<Set<NFAState>, CharObjectHashMap<Set<NFAState>>> oriDFATransitionMap, Set<NFAState> initClosure, NFAState finalNFAState) {
Map<Integer, int[]> renamedDFATransitionTable = new HashMap<>();
Map<Integer, Boolean> finalFlags = new HashMap<>();
Map<Set<NFAState>, Integer> stateRenamingMap = new HashMap<>();
int initStateAfterRenaming = -1;
int renamingStateID = 1;
// rename all states
for (Set<NFAState> nfaState : oriDFATransitionMap.keySet()) {
if (initStateAfterRenaming == -1 && nfaState.equals(initClosure)) {
// record init state id
initStateAfterRenaming = renamingStateID;
}
stateRenamingMap.put(nfaState, renamingStateID++);
}
// the rejected state 0
renamedDFATransitionTable.put(0, newRejectState());
finalFlags.put(0, false);
// construct renamed dfa transition table
for (Map.Entry<Set<NFAState>, CharObjectHashMap<Set<NFAState>>> entry : oriDFATransitionMap.entrySet()) {
Set<NFAState> ek = entry.getKey();
renamingStateID = stateRenamingMap.get(ek);
int[] state = newRejectState();
CharObjectHashMap<Set<NFAState>> ev = entry.getValue();
ev.forEachKeyValue((k, v) -> state[k] = stateRenamingMap.get(v));
renamedDFATransitionTable.put(renamingStateID, state);
finalFlags.put(renamingStateID, ek.contains(finalNFAState));
}
// split states to final states and non-final states
IntIntHashMap groupFlags = new IntIntHashMap();
for (int i = 0; i < finalFlags.size(); i++) {
boolean b = finalFlags.get(i);
groupFlags.put(i, b ? 0 : 1);
}
int groupTotal = 2;
int preGroupTotal;
do {
// splitting, group id is the final state id
preGroupTotal = groupTotal;
for (int sensitiveGroup = 0; sensitiveGroup < preGroupTotal; sensitiveGroup++) {
// <target group table, state id set>
Map<Map<Integer, Integer>, Set<Integer>> invertMap = new HashMap<>();
for (int sid = 0; sid < groupFlags.size(); sid++) {
// use state id to iterate
int group = groupFlags.get(sid);
if (sensitiveGroup == group) {
Map<Integer, Integer> targetGroupTable = new HashMap<>(CommonSets.ENCODING_LENGTH);
for (char ch = 0; ch < CommonSets.ENCODING_LENGTH; ch++) {
int targetState = renamedDFATransitionTable.get(sid)[ch];
int targetGroup = groupFlags.get(targetState);
targetGroupTable.put((int) ch, targetGroup);
}
Set<Integer> stateIDSet = invertMap.computeIfAbsent(targetGroupTable, k -> new HashSet<>());
stateIDSet.add(sid);
}
}
boolean first = true;
for (Set<Integer> stateIDSet : invertMap.values()) {
if (first) {
first = false;
} else {
for (int sid : stateIDSet) {
groupFlags.put(sid, groupTotal);
}
groupTotal++;
}
}
}
} while (preGroupTotal != groupTotal);
// determine initial group state
is = groupFlags.get(initStateAfterRenaming);
// determine rejected group state
rs = groupFlags.get(0);
// determine final group states
Set<Integer> finalGroupFlags = new HashSet<>();
for (int i = 0, groupFlagsSize = groupFlags.size(); i < groupFlagsSize; i++) {
Integer groupFlag = groupFlags.get(i);
if (finalFlags.get(i)) {
finalGroupFlags.add(groupFlag);
}
}
boolean[] fs = this.fs = new boolean[groupTotal];
for (int i = 0; i < groupTotal; i++) {
fs[i] = finalGroupFlags.contains(i);
}
// construct the final transition table
int[][] tt = new int[groupTotal][];
for (int groupID = 0; groupID < groupTotal; groupID++) {
for (int sid = 0; sid < groupFlags.size(); sid++) {
if (groupID == groupFlags.get(sid)) {
int[] oriState = renamedDFATransitionTable.get(sid);
int[] state = new int[CommonSets.ENCODING_LENGTH];
for (char ch = 0; ch < CommonSets.ENCODING_LENGTH; ch++) {
int next = oriState[ch];
state[ch] = groupFlags.get(next);
}
tt[groupID] = state;
break;
}
}
}
return tt;
}
Aggregations