Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] Annotation of /tests/vis15-bugs/parlife.diderot
ViewVC logotype

Annotation of /tests/vis15-bugs/parlife.diderot

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4916 - (view) (download)

1 : glk 4916 /* ==========================================
2 :     ## life.diderot Conway's Game of Life
3 :    
4 :     [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life)
5 :     is not in the target domain of the Diderot DSL, but it is a simple
6 :     program for demonstrating **strand communication**, a new feature relative
7 :     to previous examples. Strands are located in their domain according to a
8 :     special variable named `pos`, and strands can learn about nearby strands
9 :     via the `sphere` query. Strands have read-only access to the values of
10 :     other strands' variables *as they were at the start of the iteration*.
11 :     It would take two iterations for information to get from strand, to another,
12 :     and back.
13 :    
14 :     Diderot's strand communication was primarily intended for running particle
15 :     systems, in which particles are moving around in some domain, dynamically
16 :     changing which other strands they interact with, and the program output is a
17 :     1-D sequence (or set) of values. In this example, strands do not move,
18 :     and do not change their interacting neighbors, and the output is a rectangular
19 :     array. The `sphere` query (to find strands within some radius) will always
20 :     return the same 8 neighbors.
21 :    
22 :     This example also shows off the **snapshot** mechanism that can be used to
23 :     inspect the state of computation at each iteration, by saving the values of
24 :     the output variable(s) during execution. This is enabled by the `--snapshot`
25 :     option to the compiler:
26 :    
27 :     diderotc --snapshot --exec life.diderot
28 :    
29 :     This adds a new `-s` option to the `./life` executable, which controls the
30 :     periodicity of snapshots being saved, i.e. `-s 1` means save at every iteration,
31 :     `-s 10` means save at every tenth iteration. The default `-s 0` means that no
32 :     snapshots are saved.
33 :    
34 :     We can run Life with one of the supplied initial patterns in the `patterns`
35 :     subdirectory, like the [Gosper glider
36 :     gun](http://www.conwaylife.com/w/index.php?title=Gosper_glider_gun) (as well
37 :     as clean up any results from a previous run):
38 :    
39 :     rm -f state*{nrrd,png}
40 :     ./life -s 1 -l 200 -NN 80 -init patterns/gosperglidergun.nrrd
41 :    
42 :     which generates many `state-NNNN.nrrd` files, one for each iteration, starting
43 :     with `state-0000.nrrd` to record initialization state before the first iteration.
44 :     We can use some `unu` to turn these into an image sequence:
45 :    
46 :     unu join -i state-*.nrrd -a 2 |
47 :     unu quantize -b 8 |
48 :     unu resample -s x4 x4 = -k box -c cell |
49 :     unu dice -a 2 -ff state-%04d.png -o ./
50 :    
51 :     [ImageMagick](http://www.imagemagick.org)'s `convert` can then make an animated GIF:
52 :    
53 :     convert -delay 2 state*.png gosperglidergun.gif
54 :    
55 :     The resulting [gosperglidergun.gif](gosperglidergun.gif) looks as expected.
56 :     ========================================== */
57 :    
58 :     /* The game will be computed on an NN x NN grid. Real Conway Life programs can
59 :     compute on an effectively infinite grid, but this is not currently possible
60 :     in Diderot (at least not with this program). The grid will centered at the
61 :     origin (see "initially" below) only because the initialization patterns
62 :     available at http://www.conwaylife.com/wiki/Category:Patterns in the "Life
63 :     1.06" format seem to center their patterns around the origin. */
64 :     input int NN ("size of (square) simulation grid") = 200;
65 :    
66 :     /* The initial pattern is read in as a field, sampled on an integer grid with
67 :     linear (tent) interpolation). NOTE: By *not* specifying an named input file
68 :     here (called a "proxy" file in Diderot), the compiler currently produces a
69 :     program that is general with respect to input image size, but specialized
70 :     to sample type float (which happens to be what we're using here). */
71 :     input image(2)[] init ("initial pattern");
72 :     field#0(2)[] initF = tent ⊛ init;
73 :    
74 :     int iter = 0; // counts how many iterations have finished
75 :    
76 :     // Each strand represents one cell in the grid
77 :     strand cell (vec2 pos0) {
78 :     /* "pos" is a special strand variable: the type indicates the dimension of
79 :     the spatial domain over which strand communication happens, and the
80 :     value is the strand position in that domain. Currently, only a variable
81 :     named "pos" satisfies this role. In this case, pos is learned from the
82 :     strand initialization, and then never changed. */
83 :     vec2 pos = pos0;
84 :     /* "state" is either 1 or 0, initialized by querying the initF field at the
85 :     strand position. Diderot currently has no casting mechanism to convert a
86 :     real to an int, hence the "1 if initF(pos) > 0.5 else 0" conditional
87 :     expression that produces an int from real-valued initF(pos). */
88 :     output int state = 0 if !inside(pos, initF) else
89 :     1 if initF(pos) > 0.5 else
90 :     0;
91 :    
92 :     /* This update method computes the new state of this strand's cell from
93 :     its previous state and the previous state of its 8 neighbors */
94 :     update {
95 :     /* Count living neighbors. The cells are at integral grid positions, so
96 :     the 8 closest neighbors (use for Life) are either distance 1 away
97 :     (up, down, left, right), or distance sqrt(2) away (the diagonals). A
98 :     little extra is added to sqrt(2) for safety. */
99 :     int nn = 0;
100 :     foreach (cell c in sphere(sqrt(2)+0.001)) {
101 :     nn += c.state;
102 :     }
103 :     // Here are the rules of Life
104 :     state = 1 if (3 == nn) else
105 :     state if (2 == nn) else
106 :     0;
107 :     }
108 :     }
109 :    
110 :     /* This program uses a global update just to print a progress indication. The
111 :     assumption is that execution is being stopped via the "-l" limit on
112 :     iterations. If the program is compiled with snapshot generation enabled
113 :     ("--snapshot") and the program is run to save a snapshot at every iteration
114 :     ("-s 1"), then it will save "snap-0000.nrrd" to indicate strand state after
115 :     strands have been initialization but before the first iteration runs
116 :     (before any per-strand updates), and thereafter "snap-NNNN.nrrd" will
117 :     indicate state after the NNNN iterations have finished. In this program,
118 :     running with "-l 5" will lead to six snapshot files being saved
119 :     "snap-000{0,1,2,3,4,5}.nrrd", as well as the final output "state.nrrd".
120 :     Had the program been run as a strand collection (with "initially {}"), the
121 :     final "state.nrrd" would not be saved when running with "-l 5", but each
122 :     snapshot would be a 1D array of ints, instead of a 2D array. */
123 :     global {
124 :     print("iter ", iter, " done.\n"); // progress indication
125 :     iter += 1;
126 :     }
127 :    
128 :     initially [ cell([ii, jj])
129 :     // these index ranges center the grid on the origin
130 :     | jj in (-NN/2)..(-NN/2 + NN - 1),
131 :     ii in (-NN/2)..(-NN/2 + NN - 1) ];

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0