Prolog 序言中的斐波那契-如果为False,则中断

Prolog 序言中的斐波那契-如果为False,则中断,prolog,fibonacci,Prolog,Fibonacci,我有一个程序fib(X,Y)。如果Y是第X个斐波那契数,则返回True,否则应返回False。每当我输入错误的语句时,我的程序就会中断 fib(R,V) :- fib(0,1,R,V). fib(X, Y, 0, V) :- Y == V. fib(X, Y, R, V) :- Z is X + Y, C is R - 1, fib(Y, Z, C, V). fib(0,1) -> True fib(1,1) -> True fib(2,2) -> True fib(3,3)

我有一个程序fib(X,Y)。如果Y是第X个斐波那契数,则返回
True
,否则应返回
False
。每当我输入错误的语句时,我的程序就会中断

fib(R,V) :- fib(0,1,R,V).
fib(X, Y, 0, V) :- Y == V.
fib(X, Y, R, V) :- Z is X + Y, C is R - 1, fib(Y, Z, C, V).

fib(0,1) -> True
fib(1,1) -> True
fib(2,2) -> True
fib(3,3) -> True
fib(4,5) -> True

fib(3,5) -> Won't finish.

我做错了什么?我正在使用运行我的程序查询

这里的问题是您编写了两个子句
fib(X,Y,0,V):-
fib(X,Y,R,V):-
。Prolog使用回溯:如果一个子句已经尝试过,它将——不管成功与否——稍后也会重试下一个子句(有一些元谓词,如
once/1
,可以改变这一点)

因此,即使
R
0
或更低,Prolog也会尝试第二个子句

解决此问题的快速方法是使用第二条的防护装置:

fib(_, Y, 0, V) :-
    Y == V.
fib(X, Y, R, V) :-
    R > 0,
    Z is X + Y,
    C is R - 1,
    fib(Y, Z, C, V).
但是现在我们仍然没有一个双向关系:我们不能得到给定值V的X。这更复杂。最简单的方法可能是为此使用
clpfd

:- use_module(library(clpfd)).

fib(_, V, 0, V).
fib(X, Y, R, V) :-
    R #> 0,
    V #>= Y,
    Z is X + Y,
    C #= R - 1,
    fib(Y, Z, C, V).
  • 获取第i个斐波那契数:

    ?- fib(2,B).
    B = 2 ;
    false.
    
    ?- fib(10,B).
    B = 89 ;
    false.
    
  • 获取对应斐波那契数为某个值的i:

    ?- fib(A,1).
    A = 0 ;
    A = 1 ;
    false.
    
    ?- fib(A,2).
    A = 2 ;
    false.
    
    ?- fib(A,3).
    A = 3 ;
    false.
    
    ?- fib(A,4).
    false.
    
    ?- fib(A,5).
    A = 4 ;
    false.
    
  • 检查第i个斐波那契数是否为给定值:

    ?- fib(4,5).
    true ;
    false.
    
    ?- fib(4,6).
    false.
    
    ?- fib(4,10).
    false.
    
    ?- fib(5,8).
    true ;
    false.
    

  • 您是否尝试进行
    跟踪
    以查看发生了什么?您可能还想考虑:如果
    R<0
    ,会发生什么?您的第二个
    fib/4
    子句仍将执行。如何运行跟踪?输入
    trace.
    然后运行查询。Prolog文档对此进行了解释。如果不想再跟踪,请输入
    notrace.
    ?- fib(A,1).
    A = 0 ;
    A = 1 ;
    false.
    
    ?- fib(A,2).
    A = 2 ;
    false.
    
    ?- fib(A,3).
    A = 3 ;
    false.
    
    ?- fib(A,4).
    false.
    
    ?- fib(A,5).
    A = 4 ;
    false.
    
    ?- fib(4,5).
    true ;
    false.
    
    ?- fib(4,6).
    false.
    
    ?- fib(4,10).
    false.
    
    ?- fib(5,8).
    true ;
    false.