(我只是主要通过swi-prolog和yap的GMP库的间接用户.但我对解决这个问题非常感兴趣.)
当使用可笑的大值执行取幂时,主机系统或GMP不再能够适当地处理溢出.我已经与上述系统的开发人员进行了交谈,但他们没有看到一个简单的解决方案.
这个问题是否为其他GMP系统/用户所知?你如何处理这种溢出?
作为一个完整性检查首先测试7 ^ 7 ^ 7的值应该是:375982 ... 32343
例如,在32位系统上,查询会?- X is 13^1150000000.产生这样的溢出.以下是YAP给出的内容:
GNU gdb (GDB) 7.0-ubuntu Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu". For bug reporting instructions, please …
许多Prolog系统都有一个freeze/2谓词,一个应该有名字的谓词,geler/2因为它甚至是在Prolog-II之前发明的.
假设我对同一个变量有条件,但有两个不同的目标,即:
?- freeze(X, G1), freeze(X, G2), X=1.
Run Code Online (Sandbox Code Playgroud)
什么是首选的唤醒策略,G1首先执行还是G2首次执行?如果G1和G2确实会产生新的冻结,这也会被唤醒:
G1 :- freeze(Y, G3), Y=1.
G2 :- freeze(Z, G4), Z=1.
Run Code Online (Sandbox Code Playgroud)
G3或G4是否始终在G1和G2之间执行,或者可能是G1和G2之后执行G3或G4,甚至是以后的任何时间?
再见
我想使用键盘快捷键或命令清除 SWI-prolog 控制台内的屏幕(我猜在 Prolog 中你称之为“谓词”)。
这是类似的问题,我有点找到我需要的东西 - 有一个适合我的谓词:
write('\33\[2J').
Run Code Online (Sandbox Code Playgroud)
有没有更好(更简单)的方法来清除屏幕?
我试图call_with_depth_limit/3在 SWI-Prolog 中使用来实现迭代深化,要么我不明白它是如何工作的,要么它行为不端。我有一个例子,其中发生以下情况:
?- call_with_depth_limit(mygoal, 29, Result).
Result = 29 ;
Result = 25 ;
Result = 27 ;
Result = 27 ;
false.
Run Code Online (Sandbox Code Playgroud)
?- call_with_depth_limit(mygoal, 26, Result).
Result = depth_limit_exceeded ;
false.
Run Code Online (Sandbox Code Playgroud)
根据文档,如果目标可以用限制最大递归或更少来证明,它应该会成功。在限制为 30 的第一次调用中,我们看到结果为 25,因此我希望以 26 的限制调用它会成功。我在模块中使用约束处理规则,以防那里可能有一些交互使其行为不端。
编辑:玩过伊莎贝尔的回答后,我想我明白它的行为方式了:
看这个例子:
loop :- loop.
succeed(0).
succeed(N) :- N > 0, N1 is N - 1, succeed(N1).
fail(N) :- N > 0, N1 is N - 1, fail(N1).
Run Code Online (Sandbox Code Playgroud)
?- call_with_depth_limit(succeed(0), 1000, Result). …Run Code Online (Sandbox Code Playgroud) 我在这里找到了 Haskell 中移位重置分隔延续的示例:
Run Code Online (Sandbox Code Playgroud)resetT $ do alfa bravo x <- shiftT $ \esc -> do charlie lift $ esc 1 delta lift $ esc 2 return 0 zulu x这会:
履行
alfa履行
bravo履行
charlie绑定
x到1,从而执行zulu 1从末尾掉下来
resetT,然后跳回到后面esc 1履行
delta绑定
x到2,从而执行zulu 2从末尾掉下来
resetT,然后跳回到后面esc 2逃离
resetT,导致它产生 0
我不知道如何使用 SWI-Prolog 的shift/1和reset/3编写等效代码。
下面的代码是我的尝试。输出是相同的,但看起来很混乱和倒退,我觉得我误用了与Haskell 示例中的和Ball类似的东西。另外,我不知道该怎么办。esc 1esc 2return 0 …
continuations haskell prolog swi-prolog delimited-continuations
我有一个执行繁重计算的代码:pred(In, Out)假设执行64K 次,每次执行需要 1-10 秒。
我想使用多线程(64)机器来加快进程。我concurrent_maplist为此使用:
concurrent_maplist(pred, List_of_64K_In, List_of_64K_Out).
我得到了大约 8 倍的加速,但不会超过这个速度。我认为原因是以下通知concurrent_maplist:
请注意,此谓词的开销相当大,因此在达到加速之前,目标必须相当昂贵。
为了使目标相当昂贵,我将代码修改为:
% putting 1K pred/2 in heavy_pred/2
concurrent_maplist(heavy_pred, List_of_64_List_of_1k_In, List_of_64_List_of_1k_Out).
heavy_pred(List_of_In, List_of_Out) :-
maplist(pred, List_of_In, List_of_Out).
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是(对我而言),我没有进一步加快这种变化。
我想知道如何通过多线程进一步加快速度?
一些额外的细节:
架构:x86_64, AMD, 14.04.1-Ubuntu。
swipl -v: SWI-Prolog version 6.6.4 for amd64.
pred/2 是一个定理证明器,它采用公式并试图证明它们。它采用标准的谓词很少非标准的:cyclic_term/1,write/1,copy_term/2等。
我编写了一些谓词来解决大型调度问题,它们运行良好,但我希望它们具有更好的性能。我运行过profile/1,我看到与 CLPFD 相关的谓词占用了 99% 的时间。特别是garbage_collect- 它需要 37% 的执行时间。
现在,我能做什么?我的代码并不是特别复杂,它使用了很多cumulative/2和一些global_cardinality/2,除此之外没有什么特别的。我已经为labeling/1(ff, ffc, bisect)尝试了一些不同的选项,但没有区别(实际上,bisect 让事情变得更糟)。我试过用set_prolog_stack/2(全局限制、局部限制、全局 min_free、局部 min_free)提高内存限制。
我还能做些什么吗?
是否有任何替代实施cumulative/2或global_cardinality/2可以具有更好的性能?
我有一个类似于下面的 CSV 文件:即不是 Prolog 格式
james,facebook,intel,samsung
rebecca,intel,samsung,facebook
Ian,samsung,facebook,intel
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个 Prolog 谓词来读取文件并返回一个看起来像的列表
[[james,facebook,intel,samsung],[rebecca,intel,samsung,facebook],[Ian,samsung,facebook,intel]]
Run Code Online (Sandbox Code Playgroud)
在其他谓词中进一步使用。
我仍然是一个初学者,并从 SO 中找到了一些很好的信息并对其进行了修改以查看我是否可以得到它,但我被卡住了,因为我只生成了一个看起来像这样的列表
[[(james,facebook,intel,samsung)],[(rebecca,intel,samsung,facebook)],[(Ian,samsung,facebook,intel)]]
Run Code Online (Sandbox Code Playgroud)
这意味着当我调用内部列表的头部时,我得到(james,facebook,intel,samsung)而不是james.
这是正在使用的代码:-(在 SO 上看到并已修改)
stream_representations(Input,Lines) :-
read_line_to_codes(Input,Line),
( Line == end_of_file
-> Lines = []
; atom_codes(FinalLine, Line),
term_to_atom(LineTerm,FinalLine),
Lines = [[LineTerm] | FurtherLines],
stream_representations(Input,FurtherLines)
).
Run Code Online (Sandbox Code Playgroud)
main(Lines) :-
open('file.txt', read, Input),
stream_representations(Input, Lines),
close(Input).
Run Code Online (Sandbox Code Playgroud) 逻辑编程背后的常用数学理论禁止创建循环项,规定每次变量与项统一时都应进行发生检查。不幸的是,发生检查会非常昂贵,以至于使 Prolog作为一种编程语言变得不切实际。
但是,我运行了这些基准测试(Prolog 的基准测试)并发现 SWI Prolog 在打开和关闭发生检查 (OC) 之间存在相当小的差异(小于 20%):
OC 关闭::- set_prolog_flag(occurs_check, false).在.swiplrc(重新启动)
?- run_interleaved(10).
% 768,486,984 inferences, 91.483 CPU in 91.483 seconds (100% CPU, 8400298 Lips)
true.
?- run(1).
'Program' Time GC
================================
boyer 0.453 0.059
browse 0.395 0.000
chat_parser 0.693 0.000
crypt 0.481 0.000
fast_mu 0.628 0.000
flatten 0.584 0.000
meta_qsort 0.457 0.000
mu 0.523 0.000
nreverse 0.406 0.000
poly_10 …Run Code Online (Sandbox Code Playgroud) swi-prolog ×10
prolog ×8
biginteger ×1
c ×1
clpfd ×1
csv ×1
dcg ×1
gmp ×1
haskell ×1
http ×1
io ×1
occurs-check ×1
yap ×1