在(最好的)Prolog中解决任何问题的时间复杂性是否比天真的强力回溯实现更好?
我说Prolog语言一般......我想知道是否有一些众所周知的算法,例如做出Prolog'在Scheme中使用call / cc回溯是一个糟糕的选择。
编辑:通过"解决任何问题"我的意思是所有Prolog程序。问题中的问题":我对语言设计感到疑惑:如果完全延续对部分延续具有任何实际效用(主要优点是Prolog-esque,但它们并不严重如果他们不能与Prolog竞争时间复杂度,并且如果另一种语言可以完全吸收Prolog,或者如果通过将程序限制为Prolog形式(类似于Fortran over C中的优化)可以实现优化。
编辑:按时间复杂度,我的意思是大O,即修剪不可能用一般语言天真地模仿Prolog。答案 0 :(得分:8)
当字面翻译成Prolog时,天真的暴力搜索将保持一个天真的暴力搜索。
没关系:Plain Prolog非常适合描述和运行强力搜索。尽管如此,你仍然可能无法用Prolog编写的强力搜索击败任何暴力搜索的手动优化低级版本。另一方面,Prolog的输入非常简单方便,您很快就可以通过一些原型设计找到更好的搜索策略,而这些其他策略通常会轻易击败任何蛮力实施余量。甚至在天真地翻译时,Prolog也非常擅长回溯,并且在一些(更小或更大,取决于您使用的Prolog实现)的低级代码因素中有效。
然而,在描述搜索问题时,Prolog对许多其他语言的主要优势是约束:由于所谓的约束传播,搜索空间通常可以是修剪显着和自动。您不需要特殊规定:约束求解器将为您完成。
约束的承诺,并且承诺在很大程度上变为现实,是(1)您陈述要求和(2)Prolog引擎为您找到解决方案。查看clpfd以了解此方案的一个非常重要的实例。
因此,我提出了一个问题:在任何语言中,将一个天真的强力搜索转换为更明智的搜索策略有多容易?毕竟,这就是真正重要的改进通常会变成的方式可能的。
在Prolog中,答案通常是:非常简单。在大多数其他语言中,并非如此。
答案 1 :(得分:3)
鉴于你要求解决任何事情,Prolog肯定会在线性时间内解决问题。例如,以下append/3
谓词:
append([H|A],B,[H|R]) :-
append(A,B,R).
append([],L,L).
现在,因为在每个步骤中,只有一个候选谓词,所以没有分支,因此没有指数时间复杂度。谓词在第一个列表的长度上呈线性。
此外,可以在Prolog中允许 tabling ,这可能会导致某种动态编程,有时可以在快速算法中转换强力回溯算法。
答案 2 :(得分:2)
你问题中的问题似乎是,如果我在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版本。但你必须考虑所有方面。
总的来说,我认为让程序员适应语言比解决问题的语言更重要。
答案 3 :(得分:2)
Pure Prolog(没有" cut"操作员或命令性功能)在一个方面表现出色:对于某类问题,它是一个完整的反驳程序"。如果问题没有解决方案,Prolog程序将终止并宣布没有解决方案。另一方面,如果问题确实有解决方案,程序可能找不到或部分或全部,并且无法终止。
如果你使用命令功能或削减,所有的赌注都会关闭。
如果答案具有正确的模式,Prolog有时可以处理无数答案的问题。答案 4 :(得分:0)
另一方面,如果你的解决方案有这样的问题,Prolog可以使用它的数据库和演绎方法(所以,不是必要的强力回溯),它可能比另一个强力回溯程序有更好的性能
最后,每种编程语言最终都会创建在CPU上运行的机器代码(希望)能够解决您的问题。相同的机器代码也可以由其他语言生成,或者由程序员或多或少直接生成。所以,Prolog是解决某些问题的好方法,但它不一定是最好/最快/唯一的选择。