【问题标题】:Prolog: calculating OEIS A031877 ("nontrivial reversal numbers") using clp(FD)Prolog:使用 clp(FD) 计算 OEIS A031877(“非平凡反转数”)
【发布时间】:2015-09-16 12:10:22
【问题描述】:

浏览 awesome On-Line Encyclopedia of Integer Sequences(参见en.wikipedia.org),我偶然发现了以下整数序列:

A031877: 非平凡反转数(反转数的整数倍),不包括回文数和 10 的倍数。

通过重复使用我为回答相关问题“Faster implementation of verbal arithmetic in Prolog”而编写的一些代码,我可以 毫不费力地写下一个解决方案——感谢

:- use_module(library(clpfd)).

我们定义 核心关系 a031877_ndigits_/3 基于 digits_number/2(之前定义):

a031877_ndigits_(Z_big,N_digits,[K,Z_small,Z_big]) :-
   K #> 1,
   length(D_big,N_digits),
   reverse(D_small,D_big),
   digits_number(D_big,Z_big),
   digits_number(D_small,Z_small),
   Z_big #= Z_small * K.

核心关系是确定性的,并且普遍终止 N_digit 是一个具体的整数。请亲自查看N_digit 的前 100 个值!

?- time((N in 0..99,indomain(N),a031877_ndigits_(Z,N,Zs),false)).
% 3,888,222 inferences, 0.563 CPU in 0.563 seconds (100% CPU, 6903708 Lips)
false

让我们运行一些查询!

?- a031877_ndigits_(87912000000087912,17,_)。 true % 成功,正如预期的那样 ;错误的。 ?- a031877_ndigits_(87912000000987912,17,_)。 错误的。 % 失败,正如预期的那样

接下来,让我们找到一些包含恰好四个十进制数字的非平凡反转数:

?- a031877_ndigits_(Z,4,Zs), labeling([],Zs).
  Z = 8712, Zs = [4,2178,8712]
; Z = 9801, Zs = [9,1089,9801]
; false.

好的!让我们测量证明上述查询的普遍终止所需的运行时间!

?- time((a031877_ndigits_(Z,4,Zs),labeling([],Zs),false)).
% 11,611,502 inferences, 3.642 CPU in 3.641 seconds (100% CPU, 3188193 Lips)
false.                                % terminates universally

现在,这太长了!

我可以做些什么来加快速度?使用不同和/或其他约束?甚至可能是多余的?或者也许识别并消除削减搜索空间大小的对称性?不同的 clp(*) 域(b、q、r、set)呢?还是不同的一致性/传播技术?或者更确切地说是 Prolog 风格的协程?

有想法吗?我要他们所有!提前致谢。

【问题讨论】:

    标签: clpfd performance optimization prolog clpfd oeis


    【解决方案1】:

    到目前为止...没有答案:(

    我想出了以下...

    labeling/2 使用不同的变量怎么样?

    a031877_ndigits_(Z_big,N_digits,/* [K,Z_small,Z_big] */ [K|D_big]) :- K#>1, 长度(D_big,N_digits), 反向(D_small,D_big), 数字号码(D_big,Z_big), digits_number(D_small,Z_small), Z_big #= Z_small * K。

    让我们测量一些运行时间!

    ?- time((a031877_ndigits_(Z,4,Zs),labeling([ff],Zs),false)).
    % 14,849,250 inferences, 4.545 CPU in 4.543 seconds (100% CPU, 3267070 Lips)
    false.
    
    ?- time((a031877_ndigitsNEW_(Z,4,Zs),labeling([ff],Zs),false)).
    %    464,917 inferences, 0.052 CPU in 0.052 seconds (100% CPU, 8962485 Lips)
    false.
    

    更好!但是我们能走得更远吗?

    ?- time((a031877_ndigitsNEW_(Z,5,Zs),labeling([ff],Zs),false)).
    %  1,455,670 inferences, 0.174 CPU in 0.174 seconds (100% CPU, 8347374 Lips)
    false.
    
    ?- time((a031877_ndigitsNEW_(Z,6,Zs),labeling([ff],Zs),false)).
    %  5,020,125 inferences, 0.614 CPU in 0.613 seconds (100% CPU, 8181572 Lips)
    false.
    
    ?- time((a031877_ndigitsNEW_(Z,7,Zs),labeling([ff],Zs),false)).
    % 15,169,630 inferences, 1.752 CPU in 1.751 seconds (100% CPU, 8657015 Lips)
    false.
    

    当然还有很大的改进空间!一定有……

    【讨论】:

      【解决方案2】:

      我们可以做得更好,将数论属性转化为约束语言!

      所有项的格式为 87...12 = 4*21...78 或 98...01 = 9*10...89。

      我们在a031877_ndigitsNEW_/3的基础上实现a031877_ndigitsNEWER_/3,并直接将上述属性添加为两个有限域约束:

      a031877_ndigitsNEWER_(Z_big,N_digits,[K|D_big]) :- {4}\/{9} 中的 K,%(新) 长度(D_big,N_digits), D_big ins (0..2)\/(7..9), %(新) 反向(D_small,D_big), 数字号码(D_big,Z_big), digits_number(D_small,Z_small), Z_big #= Z_small * K。

      让我们重新运行我们之前使用的基准测试!

      ?- time((a031877_ndigitsNEWER_(Z,5,Zs),labeling([ff],Zs),false)).
      % 73,011 inferences, 0.006 CPU in 0.006 seconds (100% CPU, 11602554 Lips)
      false.
      
      ?- time((a031877_ndigitsNEWER_(Z,6,Zs),labeling([ff],Zs),false)).
      % 179,424 inferences, 0.028 CPU in 0.028 seconds (100% CPU, 6399871 Lips)
      false.
      
      ?- time((a031877_ndigitsNEWER_(Z,7,Zs),labeling([ff],Zs),false)).
      % 348,525 inferences, 0.037 CPU in 0.037 seconds (100% CPU, 9490920 Lips)
      false.
      

      总结:对于这三个查询,我们始终观察到所需的搜索量显着减少。只需考虑推理数量减少了多少:1.45M -> 73k、5M -> 179k、15.1M -> 348k。

      我们能否做得更好(同时保留代码的声明性)?不知道,大概是这样……

      【讨论】:

        猜你喜欢
        • 2019-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多