tmp
This commit is contained in:
parent
93b02416de
commit
1f1dc001a1
8 changed files with 124 additions and 60 deletions
|
|
@ -47,6 +47,7 @@ namespace tp {
|
|||
class State {
|
||||
friend FiniteStateAutomation;
|
||||
|
||||
public:
|
||||
State() = default;
|
||||
|
||||
public:
|
||||
|
|
@ -61,7 +62,7 @@ namespace tp {
|
|||
|
||||
private:
|
||||
List<State> mStates;
|
||||
const State* mStartState = nullptr;
|
||||
State* mStartState = nullptr;
|
||||
|
||||
public:
|
||||
FiniteStateAutomation() = default;
|
||||
|
|
@ -69,18 +70,18 @@ namespace tp {
|
|||
State* addState(const tStateType& state, bool accepting) {
|
||||
auto node = mStates.newNode();
|
||||
node->data.mIsAccepting = accepting;
|
||||
node->data.mState = state;
|
||||
node->data.mStateVal = state;
|
||||
mStates.pushBack(node);
|
||||
return &node->data;
|
||||
}
|
||||
|
||||
void addTransition(State* from, State* to, const tAlphabetType& symbol) {
|
||||
from->edges.pushBack(Transition(Transition::SYMBOL, to, symbol));
|
||||
from->mTransitions.append(Transition(Transition::SYMBOL, to, symbol));
|
||||
}
|
||||
|
||||
void addEpsilonTransition(State* from, State* to) { from->edges.pushBack(Transition(Transition::SYMBOL, to)); }
|
||||
void addEpsilonTransition(State* from, State* to) { from->mTransitions.append(Transition(Transition::SYMBOL, to)); }
|
||||
|
||||
void addAnyTransition(State* from, State* to) { from->edges.pushBack(Transition(Transition::ANY, to)); }
|
||||
void addAnyTransition(State* from, State* to) { from->mTransitions.append(Transition(Transition::ANY, to)); }
|
||||
|
||||
void setStartVertex(State* start) { mStartState = start; }
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ namespace tp {
|
|||
// vertices that are reachable from initial set with no input consumption (E-transitions)
|
||||
// does not include initial set
|
||||
void findClosureSet(const Buffer<State*>& from, Buffer<State*>& closureSet) const {
|
||||
Map<State*, bool> lookup;
|
||||
Map<alni, bool> lookup;
|
||||
List<State*> workingSet;
|
||||
|
||||
for (auto item : from) {
|
||||
|
|
@ -106,10 +107,11 @@ namespace tp {
|
|||
while (workingSet.length()) {
|
||||
auto first = workingSet.first()->data;
|
||||
closureSet.append(first);
|
||||
lookup.put((alni) first, {});
|
||||
|
||||
for (auto edge : first->mTransitions) {
|
||||
if (!edge.data().isEpsilon()) continue;
|
||||
if (lookup.presents(edge.data().mState)) continue;
|
||||
if (lookup.presents((alni) edge.data().mState)) continue;
|
||||
workingSet.pushBack(edge.data().mState);
|
||||
}
|
||||
|
||||
|
|
@ -119,88 +121,118 @@ namespace tp {
|
|||
|
||||
// vertices that are reachable from initial set with symbol transition
|
||||
void findMoveSet(const Buffer<State*>& from, Buffer<State*>& moveSet, tAlphabetType symbol) const {
|
||||
Map<State*, bool> lookup;
|
||||
Map<alni, bool> lookup;
|
||||
|
||||
for (auto vertex : from) {
|
||||
for (auto edge : vertex.mTransitions) {
|
||||
if (edge.data().isepsilon()) continue;
|
||||
for (auto edge : vertex->mTransitions) {
|
||||
if (edge.data().isEpsilon()) continue;
|
||||
if (!edge.data().isTransition(symbol)) continue;
|
||||
if (lookup.presents(edge.data().mState)) continue;
|
||||
if (lookup.presents((alni) edge.data().mState)) continue;
|
||||
moveSet.append(edge.data().mState);
|
||||
lookup.put(edge.data().mState, {});
|
||||
lookup.put((alni) edge.data().mState, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename tAlphabetIterator>
|
||||
bool makeDeterministic(const tAlphabetIterator& allSymbols) {
|
||||
if (!isValid()) {
|
||||
return false;
|
||||
}
|
||||
if (!isValid()) return false;
|
||||
|
||||
struct Group {
|
||||
Buffer<State*> states;
|
||||
AvlTree<Group*, tAlphabetType> transitions;
|
||||
typedef Buffer<State*> Group;
|
||||
|
||||
struct GroupKey {
|
||||
const Group* group;
|
||||
static ualni hash(GroupKey key) { return 0; }
|
||||
bool operator==(const GroupKey& key) const { return false; }
|
||||
};
|
||||
|
||||
struct GroupInfo {
|
||||
Group* group = nullptr;
|
||||
AvlTree<AvlNumericKey<alni>, tAlphabetType> transitions;
|
||||
State* newState = nullptr;
|
||||
bool accepting = false;
|
||||
tStateType stateVal = tStateType();
|
||||
};
|
||||
|
||||
struct GroupKey {
|
||||
const Group* group;
|
||||
};
|
||||
Buffer<Group> groups = { {} };
|
||||
Map<GroupKey, GroupInfo, DefaultAllocator, GroupKey::hash> groupInfos;
|
||||
|
||||
Buffer<Group> newStates = { {} };
|
||||
findClosureSet({ getStartState() }, groups.first());
|
||||
groupInfos.put({ &groups.first() }, { &groups.first() });
|
||||
|
||||
// 1) find new states
|
||||
Map<GroupKey, bool> lookup;
|
||||
List<Group*> workingSet;
|
||||
workingSet.pushBack(&groups.first());
|
||||
|
||||
findClosureSet({ getStartState() }, newStates.first().states);
|
||||
|
||||
workingSet.pushBack(&newStates.first());
|
||||
while (workingSet.length()) {
|
||||
auto group = workingSet.first();
|
||||
Group* group = workingSet.first()->data;
|
||||
GroupInfo* info = &groupInfos.get({ group });
|
||||
|
||||
for (auto symbol : allSymbols) {
|
||||
|
||||
// calculate new possible state
|
||||
Group potentialGroupTmp;
|
||||
Group potentialGroup;
|
||||
findMoveSet(group.states, potentialGroup.states, symbol);
|
||||
if (!potentialGroup.states.size()) continue;
|
||||
|
||||
findMoveSet(*group, potentialGroupTmp, symbol);
|
||||
findClosureSet(potentialGroupTmp, potentialGroup);
|
||||
|
||||
if (!potentialGroup.size()) continue;
|
||||
|
||||
// find existing or create group
|
||||
Group* targetGroup = nullptr;
|
||||
auto iter = lookup.presents({ &potentialGroup });
|
||||
auto iter = groupInfos.presents({ &potentialGroup });
|
||||
if (iter) {
|
||||
targetGroup = lookup.getSlotVal(iter);
|
||||
targetGroup = groupInfos.getSlotVal(iter).group;
|
||||
} else {
|
||||
targetGroup = newStates.append({});
|
||||
lookup.put({ targetGroup }, {});
|
||||
targetGroup = &groups.append(potentialGroup);
|
||||
groupInfos.put({ targetGroup }, { targetGroup });
|
||||
workingSet.pushBack(targetGroup);
|
||||
}
|
||||
|
||||
// add transition
|
||||
group.transitions.insert(targetGroup, symbol);
|
||||
// assert transition is added
|
||||
info->transitions.insert((alni) targetGroup, symbol);
|
||||
}
|
||||
|
||||
workingSet.popFront();
|
||||
}
|
||||
|
||||
// 2) find new states termination values
|
||||
// ...
|
||||
for (auto group : groupInfos) {
|
||||
GroupInfo* info = &group->val;
|
||||
bool accepting = false;
|
||||
for (auto item : *info->group) {
|
||||
if (item->mIsAccepting) {
|
||||
if (accepting) return false;
|
||||
accepting = true;
|
||||
info->accepting = true;
|
||||
info->stateVal = item->mStateVal;
|
||||
}
|
||||
}
|
||||
if (!accepting) {
|
||||
info->accepting = false;
|
||||
info->stateVal = info->group->first()->mStateVal;
|
||||
}
|
||||
}
|
||||
|
||||
// 3) transfer
|
||||
mStates.removeAll();
|
||||
|
||||
for (auto group : newStates) {
|
||||
group.newState = addState();
|
||||
// create states
|
||||
for (auto group : groupInfos) {
|
||||
group->val.newState = addState(group->val.stateVal, group->val.accepting);
|
||||
}
|
||||
|
||||
for (auto group : newStates) {
|
||||
for (auto transition : group.transitions) {
|
||||
addTransition(/* ... */);
|
||||
}
|
||||
// create transitions
|
||||
for (auto group : groupInfos) {
|
||||
auto functor = [&](AvlNumericKey<alni> targetGroupKey, tAlphabetType symbol) {
|
||||
GroupInfo* targetGroup = &groupInfos.get({ (Group*) targetGroupKey.val });
|
||||
addTransition(group->val.newState, targetGroup->newState, symbol);
|
||||
};
|
||||
group->val.transitions.forEach(functor);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue