| OCR Text |
Show A program that computes the first N lucky numbers without any redundant computations is given below (where the clauses are numbered for later reference): (1) gen(N) = NAgen(N+2) (2) sift(MAL, N) = MAsift(sieve(L, M, N), N+1) (3) sieve(AAL, M, N) = if M=N then sieve(L, M, 1) else AAsieve(L, M, N+1) (4) truncate(O, Infinite, []). (5) truncate(N, AAinfinite, AAFinite) :- truncate(N-1, Infinite, Finite). (6) first_N_lucky_nurnbers(N, L) :- truncate(N, 1Asift(gen(3), 3), L). The function gen is used to generate all odd numbers (since no even number can be a lucky number). The function sift incrementally outputs the first number M in the current list as a lucky number, calls on the function sieve to remove every Mth number in the list, and then starts the same process again on the remaining list. The variable N is used to count the position of each number in the list in order to determine whether the number should be removed or not. D 124 Figure 20 shows some snapshots in the execution of a parallel interpreter, resulting from the invocation of the goal first_N_lucky_numbers(3,L). In the figure, the computation is represented as a dynamically changing graph, where each of the functions and relations (which can be thought of as comput-ing agents) is represented by a square node in the graph; data constructors are repres.ented by circles, while "tokens" travel along the arcs which connect nodes. Arcs emanating from function nodes are directed, and represent input streams and output streams. Arcs emanating from relation nodes are undirected, indicating that the direction of flow of data is not predetermined. In case a function node is connected to a relation node, the arc is directed towards the relation node. This reflects the fact that the corresponding parameter in the relation is used in "input mode" (for the use of "modes" see, e.g., [88] or [13]). |