prolog中的for循环不起作用

时间:2017-01-12 19:50:06

标签: prolog

我正在尝试在Prolog中执行for循环,但这不起作用。该计划应该做到以下:

generate(N,[S,E],FinalSegments):-
   segments([S,E],Initialsegments),
   iterate_level(N,Initialsegments,FinalSegments).

当我调用generate(5,[(10,0),(-10,0)])时,第一步是,generate(5,[(10,0),(-10,0)],FinalSegments)被调用,此谓词在Startpoint (10,0)和Endpoint (-10,0)之间生成4个坐标,并将这四个ccordinates存储在列表FinalSegments中。这实际上是正确完成的。在下一步中,将调用谓词iterate_level(N,Initialsegments,FinalSegments)。 谓词iterate_level()将最后一步中的四个坐标作为名为Initialsegments的列表:

Initialsegments:([[ (10, 0), (3.333333333333333, 0)],
                 [ (3.3333, 0), (-3.5527e-15, -5.7735)], 
                 [ (-3.5527e-15, -5.77350), (-3.3333, 0)],
                 [(-3.3333, 0), (-10, 0)]])

现在iterate_level(5,Initialsegments,FinalSegments)应该是一个for循环,它应该在第一次迭代后生成16个坐标,然后在第二次迭代后生成64个坐标... 但这是我的问题,这不是真的有效,我不知道我还在做错什么。 在我看到痕迹的时候,在我看来,

iterate_level(N,Ls,F):-
   seq(0,N,Index),
   next_level_segments(Index,Ls,F).

在for循环中调用next_level_segments(Index,Ls,F)时,列表 每次迭代后应该包含四倍以上坐标的Ls不会刷新。(也许这就是问题所在)。 当我打电话给generate(3,[[(60,0),(-60,0)]],X).时,我得到四次总是相同的16坐标,但我应该得到1024个不同的坐标。 也许有人可能有时间看看这个问题给我一些帮助。 感谢

这是我迄今为止的实施:

generate(N,[S,E],FinalSegments):-
   segments([S,E],Initialsegments),
   iterate_level(N,Initialsegments,FinalSegments).
generate(N,[],[]).

seq(From,_,From).
seq(From,To,X) :-
   From<To,
   Next is From+1,
   seq(Next,To,X).

iterate_level(N,Ls,F):-
   seq(0,N,Index),
   next_level_segments(Index,Ls,F).
   %fail.

iterate_level(Ls,F).
iterate_level([],[]).

segments([(Sx,Sy),(Ex,Ey)],Ls):-
   X2 is Sx+(Ex-Sx)/3,
   Y2 is Sy+(Ey-Sy)/3,
   R1 is sqrt((X2-Sx)*(X2-Sx)+(Y2-Ey)*(Y2-Ey)),
   Phi1 is atan((Y2-Sy)/(X2-Sx)),
   X3 is X2 +R1*cos((Phi1-240)*pi/180),
   Y3 is Y2 +R1*sin((Phi1+240)*pi/180),
   X4 is X2+(X2-Sx),
   Y4 is Y2+(Y2-Sy),
   Ls=[
          [(Sx,Sy),(X2,Y2)],
          [(X2,Y2),(X3,Y3)],
          [(X3,Y3),(X4,Y4)],
          [(X4,Y4),(Ex,Ey)]

        ].    

next_level_segments(N,[[(Sx,Sy),(Ex,Ey)]|E],[X|RLs]):-
   segments([(Sx,Sy),(Ex,Ey)],X),
   next_level_segments(N,E,RLs). 
next_level_segments(N,[],[]).

1 个答案:

答案 0 :(得分:3)

所以,首先,Prolog不会做传统意义上的for循环 - 你真正想做的是用累加器递归列表。这可以通过以下方式实现。

首先,generate(0, [[X|Y]|Z], [[X|Y]|Z]) :- !.,其中说“如果我试图生成列表列表的第0次迭代,我已经实现了目标,我应该成功”。这也会减少,因为这里只有一个解决方案。

generate(N, [[P1, P2]|Tail], Final)执行(外部)递归的主体。只要这是一个正迭代(即排除否定),我们do_generate一个坐标的迭代,并递归另一个迭代(迭代0成功如上)。

do_generate([],[]).表示如果我们尝试在空列表之间生成坐标,我们就会为此级别完成。

do_generate([Current|Rest], Interim)获取第一对坐标并生成四对坐标的集合(如前所述使用segments([(Sx,Sy),(Ex,Ey)],Ls)),然后递归到坐标列表的其余部分。一旦我们达到上述基本情况,我们将所有列表从最后一个追加到第一个以获得新的坐标集。然后将其与Interim统一,以使用外部基本情况发送回generate(N, [[P1, P2]|Tail], Final)以进一步递归或与Final统一。

作为警告,为了使输出看起来像最终基本情况的输入,输入现在需要是坐标对列表的列表,而不仅仅是坐标对的列表。

全部放在一起,您得到以下内容:

generate(0, [[X|Y]|Z], [[X|Y]|Z]) :- !.
generate(N, [[P1, P2]|Tail], Final) :-
    N > 0,
    do_generate([[P1, P2]|Tail], Interim),
    N1 is N-1,
    generate(N1, Interim, Final).

do_generate([], []).
do_generate([Current|Rest], Interim) :-
    segments(Current, Segs),
    do_generate(Rest, RestSegs),
    append(Segs, RestSegs, Interim).

segments([(Sx,Sy), (Ex,Ey)], Ls) :-
   X2 is Sx+(Ex-Sx)/3,
   Y2 is Sy+(Ey-Sy)/3,
   R1 is sqrt((X2-Sx)*(X2-Sx)+(Y2-Ey)*(Y2-Ey)),
   Phi1 is atan((Y2-Sy)/(X2-Sx)),
   X3 is X2+R1*cos((Phi1-240)*pi/180),
   Y3 is Y2+R1*sin((Phi1+240)*pi/180),
   X4 is X2+(X2-Sx),
   Y4 is Y2+(Y2-Sy),
   Ls=[[(Sx,Sy),(X2,Y2)],
       [(X2,Y2),(X3,Y3)],
       [(X3,Y3),(X4,Y4)],
       [(X4,Y4),(Ex,Ey)]].