【问题标题】:Generalizing Fibonacci sequence with SICStus Prolog用 SICStus Prolog 概括斐波那契数列
【发布时间】:2010-05-09 18:34:36
【问题描述】:

我正在尝试为广义斐波那契数列 (GFS) 的查询找到解决方案。问题是:是否有任何 GFS 的第 12 个数字为 885?前 2 个数字可能被限制在 1 到 10 之间。

我已经找到了在从 (1, 1) 开始的序列中找到第 N 个数字的解决方案,其中我明确定义了初始数字。这就是我所拥有的:

fib(1, 1).
fib(2, 1).

fib(N, X) :-
    N #> 1,
    Nmin1 #= N - 1,
    Nmin2 #= N - 2,
    fib(Nmin1, Xmin1),
    fib(Nmin2, Xmin2),
    X #= Xmin1 + Xmin2.

对于提到的查询,我认为以下方法可以解决问题,其中我重用 fib 方法而不明确定义初始数字,因为现在需要动态完成:

fib(N, X) :-
    N #> 1,
    Nmin1 #= N - 1,
    Nmin2 #= N - 2,
    fib(Nmin1, Xmin1),
    fib(Nmin2, Xmin2),
    X #= Xmin1 + Xmin2.

fib2 :-
    X1 in 1..10,
    X2 in 1..10,
    fib(1, X1),
    fib(2, X2),
    fib(12, 885).

...但这似乎不起作用。

这样定义初始数字是不可能的,还是我做错了什么?我不是在寻求解决方案,但任何可以帮助我解决此问题的建议将不胜感激。

【问题讨论】:

  • 好问题。首先尝试摆脱指数递归;它会杀死你的代码。尝试为此使用累加器。

标签: prolog fibonacci sicstus-prolog clpfd


【解决方案1】:

在 SWI-Prolog 下:

:- use_module(library(clpfd)).

fib(A,B,N,X):-
    N #> 0,
    N0 #= N-1,
    C #= A+B,
    fib(B,C,N0,X).
fib(A,B,0,A).

task(A,B):-
    A in 1..10,
    B in 1..10,
    fib(A,B,11,885).

【讨论】:

  • @CookieMonster,prolog 倾向于以比其他一些语言更自然的方式表示一些搜索(例如 max(X, L):- member(X, L), not((member(Y, L), Y > X)).)。 “标签”是什么意思?
  • @CookieMonster,啊……这是 SIICSTUS Prolog 特有的。我从来没有用过那个。首选 YAP 和 SWI 示例。在这两个中都打印了所有空闲占位符。
  • @CookieMonster,我使用的是 Yap 6.2.2。在查询?- (X=2;X=3),Y is X*2. 时,它给了我X = 2, Y = 4。我可以按; 并获得替代方案。我使用交互模式(即运行 yap 没有任何其他选项)。也许这就是区别
  • @CookieMonster,是的,您获得解决方案是对的,您需要致电task(A,B), label([A,B])。在 SWI-Prolog 和 YAP 中。没有它,它只会打印约束。顺便说一句,在 Curry 中,您可以简单地编写 C=A+B,它将被暂停/推迟(类似协同程序),直到 AB 绑定到某些东西。
【解决方案2】:

定义一个谓词 gfs(X0, X1, N, F),其中 X0 和 X1 是基本情况 0 和 1 的值。

【讨论】:

    【解决方案3】:

    我会说你做错了什么...... 当您调用fib(1, X1) 时,变量X1 是函数fib 将返回的数字,在这种情况下,它将为1,因为基本情况fib(1, 1).

    【讨论】:

    • 我调用 fib2 时未定义基本情况。 fib 已定义,但没有明确的初始数字。这可能在我的问题中令人困惑,我会更新它。
    • 好的,我再看看:)
    【解决方案4】:

    没有基本情况,fib/2 没有解决方案;无论你在 fib2 中如何称呼它。 注意:如果使用递归,则至少需要一种基本情况。

    【讨论】:

      【解决方案5】:

      考虑fib(N,F1,F2),这样您就可以将fib(Nmin1, Xmin1)fib(Nmin2, Xmin2) 替换为简单的fib(Nmin2, Xmin2, Xmin1)

      【讨论】:

        【解决方案6】:

        也许不是严格意义上的解决方案,但我会永远分享它。可能唯一的收获是表明,这既不需要计算机也不需要计算器来解决。如果你知道诀窍,它可以在熊垫上完成。

        如果 F_n 是普通 Fibo 序列的第 n 项,从 F_1=F_2=1 开始,那么广义序列的第 n 项将是 G_n = F_{n-2}*a+F_ {n-1}*b。 定义 F_{-1}=1, F_0 = 0

        (确实,通过归纳

        • G_1 = F_{-1}*a+F_0*b = 1*a+0*b=a
        • G_2 = F_0 * a + F_1 * b = 0*a + 1*b = b
        • G_{n+1} = F_{n-1}a + F_nb = (F_{n-3} + F_{n-2} )a + (F_{n- 2} + F_{n-1})*b = G_n + G_{n-1}

        )

        因此 G_12 = F_10 * a + F_11 * b = 55a + 89b。

        现在您可以使用计算机搜索方程 55a + 89b = 885 的解

        算一算:

        残基 mod 11 (explanation):

        55a + 89b = 0 + 88b + b = b; 885 = 880 + 5 = 80*11 + 5 = 5

        所以 b = 5 mod 11,但由于 1

        【讨论】:

        • CLP(FD) 可能不擅长你所做的代数和归纳证明。但是 CLP(FD) 可以很好地找到诸如 55*A+89*B #= 885 等方程的解。
        猜你喜欢
        • 2017-11-13
        • 2020-07-16
        • 2015-06-05
        • 2021-09-18
        • 2013-04-15
        • 2013-08-03
        • 2014-05-19
        相关资源
        最近更新 更多