Prolog - 乘以加法

时间:2017-10-12 17:14:14

标签: prolog

我需要简单的功能在SWI-prolog中乘以加法。类似于m(X,Y,Z)的东西,例如X = 5,Z = 3< ==> 5 * 3。 Y是结果:Y = 5,Y = 10,Y = 15 [停止]。我在想这样的事情:

m(X,Y,Z):- Z>0, /*when Z reaches 0 you stop */ I=X+X, W=Z-1, m(I,Y,W).

但它总是回归"假"和dunno为什么。

1 个答案:

答案 0 :(得分:4)

让我们首先考虑一下谓词应该描述的内容:它是三个数字之间的关系,第三个数字是前两个数字的乘积。因为你想通过将第二个参数减少为零来描述乘法,而相应地将第一个参数相加多次,我们讨论的是自然数。所以一个很好描述的名字就是nat_nat_prod / 3。接下来考虑可能的情况:

  1. 第二个参数可以为零。然后产品必须为零,因为X * 0 = 0。所以这是基本情况。

  2. 否则第二个参数大于零。然后你想减一,并计算第一个参数和这个新数字的乘积。由于谓词可以用自己来描述,这是一个递归目标。随后,您将第一个参数添加到递归描述的中间产品。

  3. 这可以用Prolog编写,如下所示:

    nat_nat_prod(_X,0,0).         % case 1)
    nat_nat_prod(X,Y1,P1) :-      % case 2)
       Y1 > 0,
       Y0 is Y1-1,
       nat_nat_prod(X,Y0,P0),
       P1 is P0+X.
    

    现在让我们尝试一些问题:

    ?- nat_nat_prod(5,3,P).
    P = 15 ;
    false.
    
    ?- nat_nat_prod(5,4,P).
    P = 20 ;
    false.
    
    ?- nat_nat_prod(5,0,P).
    P = 0 ;
    false.
    
    ?- nat_nat_prod(1,0,P).
    P = 0 ;
    false.
    
    ?- nat_nat_prod(1,1,P).
    P = 1 ;
    false.
    

    但是,在使用谓词时,您会注意到前两个参数必须实例化,否则您将收到错误:

    ?- nat_nat_prod(1,Y,3).
    ERROR: >/2: Arguments are not sufficiently instantiated
    ?- nat_nat_prod(X,1,3).
    ERROR: is/2: Arguments are not sufficiently instantiated
    

    这是因为使用了> / 2并且是/ 2。你可以通过使用CLP(FD)解决这个问题,但我认为这不是重点。与使用标准算术函数* / 2相比,这种定义乘法的方式显然非常低效,例如:

    ?- time(nat_nat_prod(2,1000000,P)).
    % 3,000,000 inferences, 33.695 CPU in 33.708 seconds (100% CPU, 89035 Lips)
    P = 2000000 ;
    % 3 inferences, 0.031 CPU in 0.031 seconds (100% CPU, 97 Lips)
    false.
    
    ?- time(P is 2*1000000).
    % 1 inferences, 0.000 CPU in 0.000 seconds (86% CPU, 82325 Lips)
    P = 2000000.
    

    正如评论中@false已经暗示的那样,首先将人们引入successor arithmetics然后以这种方式用s(X)表示法定义两个数字的加法/乘法更为常见。由于您不能将标准算术函数与s(X)数一起使用,因此也不会遇到关联的实例化错误。