Prolog中的离散对数

Prolog中的离散对数,prolog,primes,pumping-lemma,halting-problem,Prolog,Primes,Pumping Lemma,Halting Problem,我想检查两个程序中的哪一个将停止: P1() { X = 819688; while (X != 77) { X = (X*12367+3466) mod 4294967296; } } P2() { X = 955725; while (X != 77) { X = (X*12367+3466) mod 4294967296; } } 由于每次迭代都是一种函数组合,最终会导致while循环中函数的幂次,我想离散对数可能会解决这个

我想检查两个程序中的哪一个将停止:

P1() {
   X = 819688;
   while (X != 77) {
      X = (X*12367+3466) mod 4294967296;
   }
}

P2() {
   X = 955725;
   while (X != 77) {
      X = (X*12367+3466) mod 4294967296;
   }
} 
由于每次迭代都是一种函数组合,最终会导致while循环中函数的幂次,我想离散对数可能会解决这个问题


解决问题的任何Prolog实现,

< P>我写了两个版本,一个是C++,使用动态编程/记忆,另一个在Prolog中,不使用它,所以它们不是直接可比的。 C++:

#包括
#包括
常量无符号长N=4294967296;
bool终止(无符号长x){//x应小于N
std::访问的向量(N,false);
而(x!=77){
如果(已访问[x])
返回false;
已访问[x]=真;
x=(x*12367+3466)%N;
}
返回true;
}
int main(){

std::cout我们可以将蛮力的性能与性能进行比较 当然。我做了一些测试,看起来 对于上面的例子,暴力似乎是不可行的 对于非终止程序。一分钟后尚未完成:

/* Brute Force */
?- time(call_with_time_limit(60,terminates(819688,N))).
% 505,081,233 inferences, 58.984 CPU in 60.000 seconds (98% CPU, 8562967 Lips)
ERROR: Unhandled exception: Time limit exceeded

?- time(terminates(955725,N)).
% 4,194,305 inferences, 0.469 CPU in 0.501 seconds (94% CPU, 8947851 Lips)
N = 2097151.
Shanks算法有一个共同的基线来初始化 索引模的一半位的缓存。但是 然后,它可以在相对较短的时间内正确地决定两个程序。有趣的是,它甚至可以在终止程序中击败暴力:

/* Shanks Algorithm */
?- time(solve(819688, N)).
% 1,179,836 inferences, 0.196 CPU in 0.205 seconds (95% CPU, 6024828 Lips)
false.

?- time(solve(955725, N)).
% 590,289 inferences, 0.137 CPU in 0.144 seconds (95% CPU, 4296792 Lips)
N = 2097151 .
开源:

Jekejeke Prolog Shanks:

SWI序言段:

MaxB暴力:

没有神奇的离散对数解算器可以快速解决所有类似问题。因为它基于LCG,所以有一种高效的算法来计算任何“幂”函数的一个很好的解释和一些非Prolog代码,请参阅。由此,您应该能够构造一个有效的解决方案。有F.Brown的论文,“任意步长的随机数生成”,Trans.Am.Nucl.Soc.(1994年11月),它实现了O(log(N))中LCG的提前跳转时间,基本上是指数运算。Python中的代码是。我并没有Prolog的经验,所以对code@MostowskiCollapse“暂停问题是指程序状态空间无限的问题。”不正确。,“暂停问题在理论上是线性有界自动机(LBAs)可判定的或者具有有限内存的确定性机器。@MostowskiCollapse“您可以阅读关于“停止问题”的stackoverflow描述……通常图灵机器“嗯”,通常“暗示”不总是我已经指出了维基百科说你不正确的地方。甚至图灵机程序也只能遇到有限的状态。你的问题显示了两个例子。@ MostowskiCollapse听起来好像你的问题和你实际问的问题不同。@ C++:即使在C++中,非记忆也是MOR。在我的系统中,C++版本只是计算N+1步,占用的时间不到一半,内存不足。记忆化的RasJaskar可能取决于输入。尝试<代码> 12345代码>代码。Prolog版本不记忆,所以我不觉得在C++中也需要演示它,尤其是。因为实现很简单。@MaxB(meta:)引号包含在双引号(或单引号)之间(有时使用其他标记,如>).back quotes,也称为backticks,表示代码段,并以这样的方式显示;因此,如果您打算将其作为引用,但实际上并不清楚,将其视为代码段非常令人困惑。:)这在过去几年中曾在meta上讨论过;我似乎记得看到过一个用户甚至在其个人资料上的状态“如果你不使用反勾号来引用,我们很可能是SO上的朋友”或者类似的话:“@MostowskiCollapse”这个离散对数建议不是我的。“那又怎么样?对于任何试图理解这条线索的人来说:OP删除了一大堆离谱的评论,其中一些声称从未说过他明确说过的话。”。((meta:)顺便说一句,你可以编辑删除的答案而不必取消删除。我自己也做过几次):)是的,我注意到有一些新功能,但我还不习惯。
/* Brute Force */
?- time(call_with_time_limit(60,terminates(819688,N))).
% 505,081,233 inferences, 58.984 CPU in 60.000 seconds (98% CPU, 8562967 Lips)
ERROR: Unhandled exception: Time limit exceeded

?- time(terminates(955725,N)).
% 4,194,305 inferences, 0.469 CPU in 0.501 seconds (94% CPU, 8947851 Lips)
N = 2097151.
/* Shanks Algorithm */
?- time(solve(819688, N)).
% 1,179,836 inferences, 0.196 CPU in 0.205 seconds (95% CPU, 6024828 Lips)
false.

?- time(solve(955725, N)).
% 590,289 inferences, 0.137 CPU in 0.144 seconds (95% CPU, 4296792 Lips)
N = 2097151 .