This commit is contained in:
IlyaShurupov 2024-02-07 16:16:41 +03:00 committed by Ilusha
parent 1f1dc001a1
commit 41aa8daeb2

View file

@ -94,93 +94,87 @@ namespace tp {
return true; return true;
} }
// vertices that are reachable from initial set with no input consumption (E-transitions) typedef AvlTree<AvlNumericKey<State*>, bool> StatesSet;
// does not include initial set
void findClosureSet(const Buffer<State*>& from, Buffer<State*>& closureSet) const { // Expands initial set with states that are reachable from initial set with no input consumption (E-transitions)
Map<alni, bool> lookup; void expandSet(StatesSet& set) const {
List<State*> workingSet; List<State*> workingSet;
for (auto item : from) { set.forEach([&](AvlNumericKey<State*>& key, bool) { workingSet.pushBack(key.val); });
workingSet.pushBack(item.data());
}
while (workingSet.length()) { while (workingSet.length()) {
auto first = workingSet.first()->data; auto first = workingSet.first()->data;
closureSet.append(first); set.insert(first, {});
lookup.put((alni) first, {});
for (auto edge : first->mTransitions) { for (auto transition : first->mTransitions) {
if (!edge.data().isEpsilon()) continue; if (!transition->isEpsilon()) continue;
if (lookup.presents((alni) edge.data().mState)) continue; if (set.find(transition->mState)) continue;
workingSet.pushBack(edge.data().mState); workingSet.pushBack(transition->mState);
} }
workingSet.popFront(); workingSet.popFront();
} }
} }
// vertices that are reachable from initial set with symbol transition // States that are reachable from initial set with symbol transition
void findMoveSet(const Buffer<State*>& from, Buffer<State*>& moveSet, tAlphabetType symbol) const { void findMoveSet(StatesSet& from, StatesSet& moveSet, tAlphabetType symbol) const {
Map<alni, bool> lookup; from.forEach([&](AvlNumericKey<State*>& key, bool) {
for (auto transition : key.val->mTransitions) {
for (auto vertex : from) { if (transition->isEpsilon()) continue;
for (auto edge : vertex->mTransitions) { if (!transition->isTransition(symbol)) continue;
if (edge.data().isEpsilon()) continue; if (moveSet.find(transition->mState)) continue;
if (!edge.data().isTransition(symbol)) continue; moveSet.insert(transition->mState, {});
if (lookup.presents((alni) edge.data().mState)) continue;
moveSet.append(edge.data().mState);
lookup.put((alni) edge.data().mState, {});
} }
} });
} }
template <typename tAlphabetIterator> template <typename tAlphabetIterator>
bool makeDeterministic(const tAlphabetIterator& allSymbols) { bool makeDeterministic(const tAlphabetIterator& allSymbols) {
if (!isValid()) return false; if (!isValid()) return false;
typedef Buffer<State*> Group;
struct GroupKey { struct GroupKey {
const Group* group; const StatesSet* group;
static ualni hash(GroupKey key) { return 0; } static ualni hash(GroupKey key) { return 0; }
bool operator==(const GroupKey& key) const { return false; } bool operator==(const GroupKey& key) const { return false; }
}; };
struct GroupInfo { struct GroupInfo {
Group* group = nullptr; StatesSet* group = nullptr;
AvlTree<AvlNumericKey<alni>, tAlphabetType> transitions; AvlTree<AvlNumericKey<StatesSet*>, tAlphabetType> transitions;
State* newState = nullptr; State* newState = nullptr;
bool accepting = false; bool accepting = false;
tStateType stateVal = tStateType(); tStateType stateVal = tStateType();
}; };
Buffer<Group> groups = { {} }; Buffer<StatesSet> groups = { {} };
Map<GroupKey, GroupInfo, DefaultAllocator, GroupKey::hash> groupInfos; Map<GroupKey, GroupInfo, DefaultAllocator, GroupKey::hash> groupInfos;
findClosureSet({ getStartState() }, groups.first()); groups.first().insert(getStartState(), false);
expandSet(groups.first());
groupInfos.put({ &groups.first() }, { &groups.first() }); groupInfos.put({ &groups.first() }, { &groups.first() });
// 1) find new states // 1) find new states
List<Group*> workingSet; List<StatesSet*> workingSet;
workingSet.pushBack(&groups.first()); workingSet.pushBack(&groups.first());
while (workingSet.length()) { while (workingSet.length()) {
Group* group = workingSet.first()->data; StatesSet* group = workingSet.first()->data;
GroupInfo* info = &groupInfos.get({ group }); GroupInfo* info = &groupInfos.get({ group });
for (auto symbol : allSymbols) { for (auto symbol : allSymbols) {
// calculate new possible state // calculate new possible state
Group potentialGroupTmp; StatesSet potentialGroup;
Group potentialGroup;
findMoveSet(*group, potentialGroupTmp, symbol); findMoveSet(*group, potentialGroup, symbol);
findClosureSet(potentialGroupTmp, potentialGroup); expandSet(potentialGroup);
if (!potentialGroup.size()) continue; if (!potentialGroup.size()) continue;
// find existing or create group // find existing or create group
Group* targetGroup = nullptr; StatesSet* targetGroup = nullptr;
auto iter = groupInfos.presents({ &potentialGroup }); auto iter = groupInfos.presents({ &potentialGroup });
if (iter) { if (iter) {
targetGroup = groupInfos.getSlotVal(iter).group; targetGroup = groupInfos.getSlotVal(iter).group;
@ -191,7 +185,7 @@ namespace tp {
} }
// assert transition is added // assert transition is added
info->transitions.insert((alni) targetGroup, symbol); info->transitions.insert(targetGroup, symbol);
} }
workingSet.popFront(); workingSet.popFront();
@ -200,18 +194,19 @@ namespace tp {
// 2) find new states termination values // 2) find new states termination values
for (auto group : groupInfos) { for (auto group : groupInfos) {
GroupInfo* info = &group->val; GroupInfo* info = &group->val;
bool accepting = false; ualni accepting = 0;
for (auto item : *info->group) {
if (item->mIsAccepting) { info->group->forEach([&](AvlNumericKey<State*>& key, bool) {
if (accepting) return false; if (key.val->mIsAccepting) {
accepting = true; accepting++;
info->accepting = true; info->accepting = true;
info->stateVal = item->mStateVal; info->stateVal = key.val->mStateVal;
} }
} });
if (!accepting) { if (!accepting) {
info->accepting = false; info->accepting = false;
info->stateVal = info->group->first()->mStateVal; info->stateVal = info->group->head()->key.val->mStateVal;
} }
} }
@ -225,8 +220,8 @@ namespace tp {
// create transitions // create transitions
for (auto group : groupInfos) { for (auto group : groupInfos) {
auto functor = [&](AvlNumericKey<alni> targetGroupKey, tAlphabetType symbol) { auto functor = [&](AvlNumericKey<StatesSet*> targetGroupKey, tAlphabetType symbol) {
GroupInfo* targetGroup = &groupInfos.get({ (Group*) targetGroupKey.val }); GroupInfo* targetGroup = &groupInfos.get({ (StatesSet*) targetGroupKey.val });
addTransition(group->val.newState, targetGroup->newState, symbol); addTransition(group->val.newState, targetGroup->newState, symbol);
}; };
group->val.transitions.forEach(functor); group->val.transitions.forEach(functor);