我正在研究一种将非确定性有限状态自动机(NFA)转换为确定性有限状态自动机(DFA)的程序。为此,我必须计算具有epsilon转换的NFA中每个状态的epsilon闭包。我已经找到了一种方法来做到这一点,但我总是认为我想到的第一件事通常是效率最低的做事方式。
以下是我如何计算简单的epsilon闭包的示例:
转换函数的输入字符串:format是startState,symbol = endState
EPS是一个epsilon过渡
1,EPS = 2
新州{12}的结果
现在显然这是一个非常简单的例子。我需要能够从任意数量的状态计算任意数量的epsilon转换。为此,我的解决方案是一个递归函数,通过查看它具有epsilon转换的状态来计算给定状态的epsilon闭包。如果该状态具有(a)epsilon转换,则在for循环内递归调用该函数,以获得与其一样多的epsilon转换。这将完成工作,但可能不是最快的方式。所以我的问题是:在Java中计算epsilon闭包的最快方法是什么?
答案 0 :(得分:4)
深度优先搜索(或广度优先搜索 - 并不重要)在图形上,其边缘是您的epilson过渡。换句话说,如果您有效地跟踪已经添加到闭包中的状态,那么您的解决方案是最佳的。
答案 1 :(得分:2)
JFLAP这样做。你可以看到他们的source - 特别是ClosureTaker.java。这是深度优先搜索(这是Peter Taylor所建议的),并且由于JFLAP使用它,我认为这是近乎最优的解决方案。
答案 2 :(得分:0)
你看过算法书了吗?但我怀疑你会找到一个明显更好的方法。但是,该算法的实际性能很可能取决于您用于实现图形的具体数据结构。您可以根据简化图表的顺序分享工作。考虑与epsilon连接并从两个不同节点引用的子图。 我不确定这是否可以以最佳方式完成,或者您是否必须采用某种启发式方法。
扫描有关算法的文献。
答案 3 :(得分:0)
只是为了让只查找@Xodarap 的答案所引用的特定代码片段的人不会发现自己需要下载源代码和应用程序来查看 jar 文件的代码,我采取了附上所述片段的自由。
public static State[] getClosure(State state, Automaton automaton) {
List<State> list = new ArrayList<>();
list.add(state);
for (int i = 0; i < list.size(); i++) {
state = (State) list.get(i);
Transition transitions[] = automaton.getTransitionsFromState(state);
for (int k = 0; k < transitions.length; k++) {
Transition transition = transitions[k];
LambdaTransitionChecker checker = LambdaCheckerFactory
.getLambdaChecker(automaton);
/** if lambda transition */
if (checker.isLambdaTransition(transition)) {
State toState = transition.getToState();
if (!list.contains(toState)) {
list.add(toState);
}
}
}
}
return (State[]) list.toArray(new State[0]);
}
不用说,所有功劳都归功于@Xodarap 和 JFLAP 项目。