/* NAME * bifur1d - plot bifurcations from a one-dimensional map * NOTES * Includes the file "maps1d.c". * MAPS * The following four one-dimensional maps are allowed: * .IP Logistic\ Map: * x(t+1) = 4 * r * x(t) * (1.0 - x(t)) * .IP Tent\ Map: * x(t+1) = (x(t) <= 0.5) ? 2 * r * x(t) : 2r * (1.0 - x(t)) * .IP Sine\ Map: * x(t+1) = sin(x(t) * PI * aux * 2 * r) / 2 + 0.5 * .IP Gaussian\ Map: * x(t+1) = r * exp(-aux * (x(t) - 0.5) * (x(t) - 0.5)) * .LP * See the file "maps1d.c" to see how to add user-defined maps. * BUGS * No sanity checks are performed to make sure that any of the * options make sense. * AUTHOR * Copyright (c) 1997, Gary William Flake. * * Permission granted for any use according to the standard GNU * ``copyleft'' agreement provided that the author's comments are * neither modified nor removed. No warranty is given or implied. */ #include #include #include #include "misc.h" int width = 640, height = 480, skip = 500, box = 0; int mag = 1, invert = 0; double rmin = 0.0, rmax = 1.0, factor = 2.0, aux = 1.0; double ymin = 0.0, ymax = 1.0, brmin, brmax, bymin, bymax; char *term = NULL, *func = "log"; char help_string[] = "\ A bifurcation diagram is plotted for a one-dimensional map \ according to the specified options. In general, the map is iterated \ for several different values of the 'r' parameter so that the long \ term behavior of the map can be observed as a function of \ 'r'. See the MAPS section of the manual page for details of what maps \ are supported. User defined maps can be added to the file maps1d.c, \ but you must recompile the program. \ "; OPTION options[] = { { "-width", OPT_INT, &width, "Width of the plot in pixels." }, { "-height", OPT_INT, &height, "Height of the plot in pixels." }, { "-skip", OPT_INT, &skip, "Number of initial points to skip." }, { "-rmin", OPT_DOUBLE, &rmin, "Smallest value for r." }, { "-rmax", OPT_DOUBLE, &rmax, "Largest value for r." }, { "-func", OPT_STRING, &func, "Map function to use (one of 'log', 'tent', 'sin', or 'gauss')." }, { "-factor", OPT_DOUBLE, &factor, "Multiplicative factor for number of iterates." }, { "-ymin", OPT_DOUBLE, &ymin, "Smallest value for y range." }, { "-ymax", OPT_DOUBLE, &ymax, "Largest value for y range." }, { "-aux", OPT_DOUBLE, &aux, "Auxiliary map parameter." }, { "-box", OPT_INT, &box, "Line width for a box." }, { "-brmin", OPT_DOUBLE, &brmin, "Smallest r-value for the box." }, { "-brmax", OPT_DOUBLE, &brmax, "Largest r-value for the box." }, { "-bymin", OPT_DOUBLE, &bymin, "Smallest value for box y range." }, { "-bymax", OPT_DOUBLE, &bymax, "Largest value for box y range." }, { "-inv", OPT_SWITCH, &invert, "Invert all colors?" }, { "-mag", OPT_INT, &mag, "Magnification factor." }, { "-term", OPT_STRING, &term, "How to plot points." }, { NULL, OPT_NULL, NULL, NULL } }; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "maps1d.c" int main(int argc, char **argv) { extern int plot_mag; extern int plot_inverse; int i, j; double x, xt, xtt, xttt, xtttt, r, rinc, tol; double (*f)(double, double); get_options(argc, argv, options, help_string); plot_mag = mag; plot_inverse = invert; plot_init(width, height, 2, term); plot_set_all(0); /* Set ranges to requested (if reasonable) values. */ rmin = (rmin < 0.0) ? 0.0 : (rmin > 1.0) ? 1.0 : rmin; rmax = (rmax < 0.0) ? 0.0 : (rmax > 1.0) ? 1.0 : rmax; plot_set_range(rmin, rmax, ymin, ymax); f = get_named_function(func); /* One pixel represents this much change in r. */ rinc = (rmax - rmin) / (width - 1); /* Tolerance for detecting periodic behavior. */ tol = 0.01 / height; /* For each value of r ... */ for(i = 0, r = rmin; i < width; i++, r += rinc) { /* The following is needed for float rounding errors. */ if(r > 1.0) r = 1.0; /* Start iterating the system to skip some points. */ x = 0.5; for(j = 0; j < skip; j++) x = f(x, r); /* Set previous iterates to nonsense values so that the test * below initially fail. */ xtttt = 5.0; xttt = 4.0; xtt = 3.0; xt = 2.0; /* We only need to do this next loop a number of times * proportional to the height of the plot since there are only * a small finite number of points that can be on. */ for(j = 0; j < height * factor; j++) { /* Save previous values. */ xtttt = xttt; xttt = xtt; xtt = xt; xt = x; x = f(x, r); plot_point(r, x, 1); /* Check for period 1, 2, 3, or 4 values, and if found within * a reasonable tolerance, bailout to speed up the computation * of the whole image. */ if(fabs(x - xt) < tol || fabs(x - xtt) < tol || fabs(x - xttt) < tol || fabs(x - xtttt) < tol) break; } } /* Plot a box, if appropriate. */ plot_inverse = 0; if(box > 0) plot_box(brmin, bymax, brmax, bymin, box); plot_finish(); exit(0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */