* * * * *

                       Programs from the past, Part II

I could have sworn I wrote a bit more about a program I wrote [1] while at
FAU (Florida Atlantic University) [2]; specifically, just how long it took to
run back then vs now (or rather, a few years ago), but having failed to find
any using Google [3] or locally searching the entries on the server, I ended
up spending all day yesterday reading through ten years of archives and still
not finding anything, I guess I haven't.

Well. [Deep subject. —Editor] [Shut up you! —Sean]

So I wrote a series of programs to search through the domain of the following
pair of equations:

x = (Ay + B) x (1 - x)
y = (Cx + D) y (1 - y)

The intent was to generate a large number of (x y) pairs and plot the results
for a given set of values for A, B, C and D. Something like:

[Window showing a chaotic attractor] [4]

[Control window for chaotic attractor] [5]

The top window shows the resulting chaotic attractor [6] when A is 2.4375, B
is 1.5624, C is -0.8659 and D is 4.0 as you loop through the above two
equations 15,000 times to generate 15,000 points (all between 0 and 1 for
both the x and y axis). And the thing about a chaotic attractor is, the
initial starting point (x and y) is largely immaterial (but not quite, as the
starting values must be between somewhere between 0 and 1). Any given value
for x and y will result in the same figure being drawn for the given values
of A, B, C and D.

The program shown allows you to change the settings of the four controlling
variables A, B, C and D by sliding the named boxes horizontally (the botton
one allows you to slide multiple variables at the same time—in this case, A
and C will slide to the left if you slide the bottom box to the left).

That was fine, but my bosses at the time wanted another view generated—a
“map” of the chaotic attractors, if you will. To generate this “map,” first
you calculate how many points are generated before you settle into an
attractor:

-----[ C ]-----
int mainloop(const double A,const double B,const double C,const double D)
{
 double xn,xn1;
 double yn,yn1;
 int    ix;
 int    iy;
 int    count;
 bool   pix[DIM][DIM]; /* have we seen this (xy) pair yet? */

 memset(pix,0,sizeof(pix));

 for (count = 0 , xn = yn = 0.5 ; count < MAXLOOP ; count++)
 {
   xn1 = ((A * yn) + B) * xn * (1.0 - xn);
   yn1 = ((C * xn) + D) * yn * (1.0 - yn);
   xn  = xn1;
   yn  = yn1;

   /* exit if we're outside the bounds */

   if (xn <  0.0) return MAXLOOP;
   if (xn >= 1.0) return MAXLOOP;
   if (yn <  0.0) return MAXLOOP;
   if (yn >= 1.0) return MAXLOOP;

   ix  = (int)(xn * DIM);
   iy  = (int)(yn * DIM);

   if (pix[ix][iy])
     break;
   pix[ix][iy] = true;
 }

 return(count);
}
-----[ END OF LINE ]-----

The assumption—if this returns MAXLOOP, there is no attractor for the given
set of values for A, B, C and D; othersise it's an indication of how quickly
(or how “showey”) we settle into the pattern.

Then it's a matter of going through a range of values and for the map images,
since they're two dimensional, I only sweep through two of the four governing
variables over their range:

> for (A = -4.0 ; A <= 4.0 ; A += 0.016)
>   for (B = -4.0 ; B <= 4.0 ; B += 0.016)
>     plot(A,B,count_as_color(mainloop(A,B,-0.8659,4.0));
>

(count_as_color() just maps a count to a color)

And we end up with an image something like:

[Map of chaotic attractors] [7]


In this image, A is the horizontal axis, going left to right from -4.0 to
4.0, and B is the veritcal axis, going, bottom to top, from -4.0 to 4.0; C
and D are fixed, at -0.8659 and 4.0 respectively. The red plus in the upper
right hand quadrant is the location of the “French horn” attractor above. The
black area represents areas that have no chaotic attractor.

But my bosses didn't just want one map—no, they wanted a larger set. So, I
generated a series of images as this, each image having a different value for
C. And while the map may not change drastically—for instance, if we bump C up
a notch to -0.8499:

[It's different; it's subtle, but it's different] [8]


The resulting chaotic attractor is completely different:

[Window showing a slightly different chaotic attractor] [9]

[Control window for the slightly different chaotic attractor] [10]

And I generated a ton of maps by looping through values of C from -4.0 to 4.0
500 images in total.

Now, when I did this the first time, twenty years (or a bit more—maybe up to
twenty-two years ago) I was doing this on a state of the art Unix
workstation, an SGI [11] workstation (perhaps you've seen their commerical
[12]?). It cost $30,000 and it took a year to generate the 500 images. Each
individual image took some ten hours to generate.

Fast forward to today. On a laptop that is maybe two years old now. I reran
the code and was able to generate an entire image (in fact, both of the map
images above) in only 8 seconds.

With four cores, that means, on a two year old laptop that might have cost
$1,500 (tops) would take 17 minutes what it took me a year to generate twenty
years ago.

Oh, and about those eight seconds [13] …

[DELETED-Update on August 5^th, 2013

Oops, I made a slight mistake [14] …


-DELETED]

Update on Tuesday, August 6^th, 2013

Mistakes were made alright [15].


[1] gopher://gopher.conman.org/0Phlog:2004/06/09.2
[2] http://www.fau.edu/
[3] http://www.google.com/
[4] gopher://gopher.conman.org/gPhlog:2013/08/04/output1.gif
[5] gopher://gopher.conman.org/gPhlog:2013/08/04/control1.gif
[6] http://en.wikipedia.org/wiki/Attractor
[7] gopher://gopher.conman.org/IPhlog:2013/08/04/map1.png
[8] gopher://gopher.conman.org/IPhlog:2013/08/04/map2.png
[9] gopher://gopher.conman.org/gPhlog:2013/08/04/output2.gif
[10] gopher://gopher.conman.org/gPhlog:2013/08/04/control2.gif
[11] http://en.wikipedia.org/wiki/Silicon_Graphics
[12] http://www.imdb.com/title/tt0107290/
[13] gopher://gopher.conman.org/0Phlog:2013/08/04.2
[14] gopher://gopher.conman.org/0Phlog:2013/08/05.1
[15] gopher://gopher.conman.org/0Phlog:2013/08/06.1

Email author at [email protected]