【问题标题】:Time complexity of Prolog better than naive brute force?Prolog 的时间复杂度比天真的蛮力更好?
【发布时间】:2015-12-23 17:19:26
【问题描述】:

在(最好的)Prolog 中解决任何问题的时间复杂度是否比天真的蛮力回溯实现更好?

我一般说 Prolog 语言...我想知道是否有一些众所周知的算法,例如,这会使在 Scheme 中使用 call/cc 回溯的“做 Prolog”成为一个糟糕的选择。

编辑:“解决任何问题”是指所有 Prolog 程序。 “问题中的问题”:我想知道语言设计:完全延续是否比部分延续有任何实际效用(主要优点是 Prolog 式的,但如果它们不能在时间复杂度上竞争,这并不严重使用 Prolog),以及如果另一种语言可以完全吸收 Prolog,或者如果通过将程序限制为 Prolog 形式来进行优化(类似于 Fortran 在 C 上可能进行的优化)。

编辑:时间复杂度是指大 O,即修剪不可能用通用语言天真地模拟 Prolog。

【问题讨论】:

  • 解决什么是什么意思?
  • 我不清楚您指的是哪种复杂性...也就是说,Prolog 实现通常在回溯时回收内存的开销非常低(与 Scheme 调用/ cc)。

标签: c prolog scheme


【解决方案1】:

字面意思翻译成 Prolog 时,天真的蛮力搜索将保持天真的蛮力搜索。

没关系:Plain Prolog 非常适合描述和运行蛮力搜索。尽管如此,使用 Prolog 编写的蛮力搜索,您可能无法击败任何蛮力搜索的手动优化低级版本。另一方面,Prolog 输入起来非常简单方便,您可能很快就会通过一些原型设计找到更好的搜索策略,并且这些其他策略通常会轻松击败任何巨大的暴力实施利润。即使翻译得天真烂漫,Prolog 也非常擅长回溯,并且可以在较低级别代码的某些(更小或更大,取决于您使用的 Prolog 实现)因素内有效地进行。

然而,在描述搜索问题时,Prolog 相对于许多其他语言的主要优势是约束:由于所谓的约束传播,搜索空间通常可以修剪显着自动。您不需要特殊规定:约束求解器会为您完成。

约束的承诺,并且这个承诺在很大程度上已经变成了现实,是(1)你陈述需求,(2)Prolog引擎为你找到解决方案。查看 了解该方案的一个非常重要的实例。

因此我提出一个问题:在任何语言中,将天真的蛮力搜索转换为更明智的搜索策略有多容易? 毕竟,真正显着的改进通常是这样变成的可能。

在 Prolog 中,答案通常是:非常简单。在大多数其他语言中,没有那么多。

【讨论】:

    【解决方案2】:

    如果您要求解决任何问题,Prolog 肯定会在线性时间内解决一些问题。例如下面的append/3 谓词:

    append([H|A],B,[H|R]) :-
        append(A,B,R).
    append([],L,L).
    

    现在因为在每一步中,只有一个候选谓词,没有分支,因此没有指数时间复杂度。谓词与第一个列表的长度呈线性关系。

    此外,可以在 Prolog 中允许 tableing,这可能会导致某种动态编程,有时可以在快速算法中转变蛮力回溯算法。

    【讨论】:

    • 对于append([VeryBigTerm1,...],[],[BT1,...]) 之类的查询,使用append/3 会产生很多开销。因此,列表中包含的术语不仅是长度,在某种程度上也是如此。
    【解决方案3】:

    您的问题似乎是,如果我在 Scheme 中编写类似 Prolog 的代码,它的性能是否会比在 Prolog 中编写 Prolog 更差?

    没有直接的答案。事实是,问题中很好地映射到 Prolog 的部分可能会比​​在 Prolog 中表现得更差。为什么?因为 Prolog 的内在函数都是用 Prolog 编写的,而您的内在函数都是用 Scheme 编写的。正如@CommuSoft 在append/3 中指出的那样,内在函数的Prolog 实现能够利用Prolog 的优势。你将在这些部分进行一场艰苦的战斗。此外,我们拥有的 Prolog 实现已经足够老了,已经花费了数十年的时间来提高统一的性能,因为这是这里有趣的领域。

    同时,大多数实质性的 Prolog 程序最终都会以一些程序位结束。这些位可能与 C 或 Scheme 没有竞争力,因为优化它们并没有那么有趣,而且对此进行的任何研究都是在 Scheme 和 ML 中进行的。所以你会在这些领域获胜。

    作为Scheme 用户,我认为您会发现以Scheme 风格编写程序更有利可图:函数式,加上一些宏来给它一种声明式的感觉。如果你有一个对 Prolog 来说非常好的问题,你可以随时向它抛出 miniKanren,但不要将它与你的程序的其余部分隔离开来。让你的语言成为你的语言。

    我不同意@ahuemmer 关于 C 与 Prolog 的区别,只是因为劳动力是有限的,而且程序除了性能之外还有很多方面。 C 的作者成本要高得多,因此您将更加努力地采用较差的策略,并最终得到不太灵活的代码。即使您将问题空间限制在小而明确的范围内,Prolog 程序员也将有更多时间进行试验并发现更好的解决方案,可能具有更好的时间复杂度。如果我们谈论无限量的劳动力,C 版本可能会胜过第一个 Prolog 版本。但你必须考虑所有维度。

    总的来说,我认为让程序员适应语言比让语言适应问题更重要。

    【讨论】:

      【解决方案4】:

      Pure Prolog(没有“cut”运算符或命令式特性)在一个方面表现出色:对于某一类问题,它是一个“完整的反驳程序”。如果问题没有解决方案,Prolog 程序将终止并宣布没有解决方案。另一方面,如果问题确实有解决方案,程序可能找不到或找到部分或全部,并且无法终止。

      如果你使用命令式功能或削减,所有的赌注都没有。

      如果答案具有正确的模式,Prolog 有时可以处理具有无限多个答案的问题。

      【讨论】:

      • 差不多:“如果问题没有解决方案”,Prolog不一定会终止。
      【解决方案5】:

      恕我直言,这取决于问题。如果它真的只能通过蛮力和回溯来解决,我认为(即使是理想化的“最佳”)Prolog 也不会比 e 更快。 G。一个编写良好的 C 程序。

      另一方面,如果你有这样的问题,Prolog 可以使用它的数据库和演绎方法(因此,不一定是暴力回溯),它可能比另一个暴力回溯程序有更好的性能.

      最后,每种编程语言最终都会创建在您的 CPU 上运行的机器代码,以(希望)解决您的问题。相同的机器代码也可以由其他语言或或多或少直接由程序员生成。所以,Prolog 是解决某些问题的好方法,但它不一定是最好的/最快的/唯一的选择。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-28
        • 2019-08-08
        • 1970-01-01
        • 2014-12-11
        • 1970-01-01
        • 2022-06-16
        • 2014-02-16
        • 1970-01-01
        相关资源
        最近更新 更多