Prolog逻辑流程

时间:2012-04-16 20:44:07

标签: prolog logic

我是Prolog的新手并且正在完成家庭作业。我的程序应该采用两个相等长度的列表,并执行D = sqrt((X1-Y1)^ 2 +(X2-Y2)^ 2 + ... +(XN-YN)^ 2)。我已经编写了代码来获得正确的答案,但它没有正确呈现。我认为它可能是逻辑流程的一个问题,因为它似乎以无限循环结束。它应该看起来像:

?- distance([1,2,3], [2,3,4], D).
D = 1.732051.

我的代码给了我正确的结果,但它打印出来像:

?- distance([1,2,3],[2,3,4],D).
1.732051
true

只是因为我有一条线来打印结果。它也没有结束(没有句号),直到我进入,这就是为什么我担心我有一个循环。如何重新编写代码或重定向逻辑,使其正常打印?

distance([],[],D) :-
  F is sqrt(D),
  format("~f~n", [F]).

distance([A|T1], [B|T2], D) :-
  var(D),
  S is (A-B)*(A-B),
  distance(T1, T2, S);
  C is A-B,
  E is C*C,
  F is D+E,
  distance(T1, T2, F).

3 个答案:

答案 0 :(得分:2)

您的程序不会进入无限循环,否则您很可能会在某个时刻出现堆栈溢出错误。 发生的事情是你的代码留下了一个开放的选择点,所以最终解释器试图重做(失败)。 您没有按预期获得结果,因为调用过程中使用的变量D永远不会被绑定。

你最好解决这个问题,思考如何递归建模。在这种情况下,您可以例如在输入列表为空时和不存在时分割问题(​​我在这里假设调用带有空列表的过程将导致结果为0)。

因此,在这种情况下,您将创建两个子句,一个用于基本情况(空列表),另一个用于递归步骤。我还将使用prolog中使用的常用方法,包括使用累加器。

因此我们为distance / 3创建一个事实,它将调用另一个使用此累加器的过程:

distance(L1,L2,F) :-
    distance(L1, L2, 0, F).

我们使用累加器来保存代码中项目差异(A-B)*(A-B)之和的部分结果:

现在我们从基本案例(空列表)开始:

distance([],[],S,F) :-
  F is sqrt(S).

这里我们说明当没有剩余项目时的结果是累加器的平方根。

我们现在遵循递归步骤,即计算每个列表中第一项的平方项差异并进行递归。

distance([A|T1], [B|T2], D, SQRT) :-
  S is D+(A-B)*(A-B),
  distance(T1, T2, S, SQRT).

现在我们完成了:

?- distance([1,2,3],[2,3,4],D).
D = 1.7320508075688772.

答案 1 :(得分:0)

我不理解format函数的使用,所以我所能做的只是提供我自己的尝试。我认为你的尝试有一个缺点,就是递归的基本情况没有明确说明。

请考虑我的方法:

distance([],[],0).
distance([A],[A],0).
distance([A|T1],[B|T2],D) :-
    distance(T1,T2,F),
    D is sqrt((A-B)*(A-B) + F*F).

答案 2 :(得分:0)

我认为你应该使用累加器:

distance(L1, L2, D) :- 
    distance(L1, L2, 0, D).

distance([], [], TT, D) :-
    D is sqrt(D).

distance([X1 | Y1], [X2 | Y2], TT, D) :-
    TT1 is TT + (X1 - X2) * X1 - X2),
    distance(Y1, Y2, TT1, D).
相关问题