【问题标题】:What is the fastest way to compute an epsilon closure?计算 epsilon 闭包的最快方法是什么?
【发布时间】:2011-02-14 08:10:41
【问题描述】:

我正在开发一个将非确定性有限状态自动机 (NFA) 转换为确定性有限状态自动机 (DFA) 的程序。为此,我必须计算 NFA 中每个具有 epsilon 转换的状态的 epsilon 闭包。我已经想出了一种方法来做到这一点,但我总是认为我首先想到的通常是做某事效率最低的方法。

以下是我如何计算简单 epsilon 闭包的示例:

转换函数的输入字符串:格式为startState,symbol = endState

EPS 是一个 epsilon 转换

1,每股收益 = 2

导致新状态 { 12 }

现在显然这是一个非常简单的例子。我需要能够从任意数量的状态计算任意数量的 epsilon 转换。为此,我的解决方案是一个递归函数,它通过查看它有一个 epsilon 转换到的状态来计算给定状态的 epsilon 闭包。如果该状态具有(一个)epsilon 转换,则在 for 循环中递归调用该函数,以获取尽可能多的 epsilon 转换。这将完成工作,但可能不是最快的方法。所以我的问题是:在 Java 中计算 epsilon 闭包的最快方法是什么?

【问题讨论】:

  • 澄清一下:Epsilon-NFA N 的 epsilon 闭包只是一个没有 epsilon 转换的 NFA?
  • @tkr 一个 epsilon 闭包不适用于 NFA。它应用于具有 1 个或多个 epsilon 转换到其他状态的状态,并返回单个状态。它用于在转换为 DFA 时摆脱 epsilon 转换,因为 DFA 不能有 epsilon 转换。
  • @Darkhydro,您不能只是将所有 epsilon 可达状态折叠在一起。考虑 s1--a-->s2, s1--b-->s3, s2--eps->s3, s2--c-->s4,开始状态 s1,接受状态 s4。如果您将 s2 和 s3 折叠成一个状态,则您接受字符串 bc,而原始 NDFA 不接受该字符串。
  • @Peter 我明白你的意思。我正在调查这个。
  • @Peter 实际上它不会接受 b。状态 1 仍将在输入 b 上转换为 3,而不是 23。创建状态 23 不会擦除状态 3。

标签: java optimization finite-automata


【解决方案1】:

深度优先搜索(或广度优先搜索 - 并不重要)在边缘是您的 epilson 转换的图上。因此,换句话说,只要您有效地跟踪已添加到闭包中的状态,您的解决方案就是最佳的。

【讨论】:

  • @Peter 搜索并不是我想要的。这更像是一个条件遍历。不过,我的模式与深度优先搜索非常相似。
  • @Darkhydro,据我了解,您正在搜索从给定状态中可到达的所有状态 epsilon-reachable 的问题。
  • @Peter 这是一种合理的看待事物的方式。但是,如果搜索只返回一个状态,我将不得不多次搜索才能获得所有状态,这会比我的实现慢,因为每次搜索都从头开始。
  • @Darkhydro,我的印象是,您会发现了解数据结构和算法的介绍并阅读深度优先搜索很有用。我书架上的一本是 Cormen、Leiserson 和 Rivest 的算法导论
  • @Peter 也许我看错了。我有自己的算法文献,并且会复习深度优先搜索。我理解它搜索的方式只返回 1 个结果。
【解决方案2】:

JFLAP 这样做。你可以看到他们的source - 特别是 ClosureTaker.java。这是深度优先搜索(这是 Peter Taylor 建议的),由于 JFLAP 使用它,我认为这是接近最优的解决方案。

【讨论】:

  • 这被证明是最好的解决方案。非常明确,因为我可以查看源代码。谢谢!
【解决方案3】:

你看过算法书吗?但我怀疑你会找到更好的方法。但是这个算法的实际性能很可能取决于你用来实现你的图的具体数据结构。您可以共享工作,具体取决于您简化图表的顺序。考虑一下 epsilon 连接并从两个不同节点引用的子图。 我不确定这是否可以以最佳方式完成,或者您是否必须求助于一些启发式方法。

浏览有关算法的文献。

【讨论】:

  • 我同意,性能将基于我使用的数据结构。如果您可以建议最佳数据结构和遍历算法,那将是最佳答案。我当前的数据结构只是一个列表/树。
【解决方案4】:

只是为了让那些只寻找@Xodarap 的答案所引用的特定代码 sn-p 的人不会发现自己需要下载源代码和应用程​​序来查看 jar 文件的代码,我冒昧地附上了所说的sn-p。

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 项目。

【讨论】:

    猜你喜欢
    • 2017-06-27
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    相关资源
    最近更新 更多