prolog中的for循环不';行不通

prolog中的for循环不';行不通,prolog,Prolog,我试图在Prolog中做一个for循环,但它不起作用。该计划应做到以下几点: generate(N,[S,E],FinalSegments):- segments([S,E],Initialsegments), iterate_level(N,Initialsegments,FinalSegments). generate(0, [[X|Y]|Z], [[X|Y]|Z]) :- !. generate(N, [[P1, P2]|Tail], Final) :- N >

我试图在Prolog中做一个for循环,但它不起作用。该计划应做到以下几点:

generate(N,[S,E],FinalSegments):-
   segments([S,E],Initialsegments),
   iterate_level(N,Initialsegments,FinalSegments).
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)]].
当我调用
generate(5,[(10,0),(-10,0)]
时,第一步是调用
generate(5,[(10,0),(-10,0)],FinalSegments)
,该谓词在起始点
(10,0)
和端点
(-10,0)
之间生成4个坐标,并将这四个对应项存储在列表
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\u level\u段(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,[],[]).
生成(N[S,E],最终片段):-
分段([S,E],初始分段),
迭代_级别(N,初始段,最终段)。
生成(N,[],[])。
seq(From,u,From)。
序号(从,到,X):-

从开始,首先,Prolog并不是传统意义上的循环——实际上,您要做的是使用累加器在列表上递归。这可以通过以下方式实现

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

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

do_generate([],[])。
指出,如果我们试图在空列表之间生成坐标,则此级别的操作已完成

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

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

所有这些加在一起,您可以得到以下结果:

generate(N,[S,E],FinalSegments):-
   segments([S,E],Initialsegments),
   iterate_level(N,Initialsegments,FinalSegments).
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)]].

因此,首先,Prolog不适用于传统意义上的循环——实际上,您要做的是使用累加器在列表上递归。这可以通过以下方式实现

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

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

do_generate([],[])。
指出,如果我们试图在空列表之间生成坐标,则此级别的操作已完成

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

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

所有这些加在一起,您可以得到以下结果:

generate(N,[S,E],FinalSegments):-
   segments([S,E],Initialsegments),
   iterate_level(N,Initialsegments,FinalSegments).
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)]].