25 Years of Programming
An open source source for C, C++, OWL, BASIC, MDB, XLS, DOT, and more...
Home   Projects   Up   Sitemap   Search   Blog   Forum+Chat   About Us   Privacy   Terms of Use   Feedback   FAQ   Images   Services   Ads   Donate   Humor

Logistic map bifurcation diagram,
equation instability,
deterministic chaos

Bif.cpp displays the logistic map bifurcation diagram of the equation X=RX(1-X) as discovered by Robert May and described in James Gleick's book, Chaos and other books about chaos and fractals. It was developed with Borland C++ 4.0 for MSDOS 6, and uses Borland BGI graphics.

There are at least 3 other versions of this program on the site (ancestors and descendants of this one), which you can find by using Search above or Live Search Site below to search for Bif or bifurcation. The best is WBif.

bif.cpp

/*	bif.cpp				2/25/03
	Copyright (C)1990-1997, 2003, 2006 Steven Whitney.
	Initially published by http://25yearsofprogramming.com.

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License (GPL)
	Version 2 as published by the Free Software Foundation.
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

shows Robert May's bifurcation diagram, (also known as the logistic map),
as described in Chaos: Making a New Science, by James Gleick.

7-4-95
finally figured what order to do things in in the loop. (beware of changing)
added <g>raph mode.  it's kind of a mess the way it's nestled in among
the original program, but should be easy to change, move, or remove,
depending on whether it's worth keeping (yes), or expanding into a
split-screen mode (no).

TO DO

remember possible problems with text output while in graphics mode

add an outer loop in main() to allow automatically (or graphically)
shifting center of display or zooming closer into a region and recalculating.
Also could allow moving a dot cursor to a point on the
diagram, and displaying the <g>raph for that point.

*/
#include <dos.h>
#include <graphics.h>
#include <math.h>
#include "c:\bcs\my.h"
#pragma hdrstop

#include "c:\bcs\mylib.cpp"
#include "c:\bcs\library\music.cpp"

//////////////////////////////////////////////////////////////////////////////

enum SoundModes { CHROMATICMODE, LINEARMODE, MAJORSCALEMODE };

//////////////////////////////////////////////////////////////////////////////
int main()
{
Scale scale;
int maxdups = 100;			// most duplicate points allowed; (determines point
							// density & predominant color of screen)
int screenx, screeny;		// screen coordinates
int color;					// color to use
BOOL beepon = FALSE;		// whether to use sound
BOOL pause = FALSE;			// whether to pause when a cycle is found
int bifmode;				// <w>hole bifurcation diagram
							// <g>raph for each R value
							// <b>oth (not supported)
double hibound, lobound;	// values for R
double mindiff = .000001;   // the minimum difference to consider 2 doubles equal
							// if too small, fails to report obvious cycles
							// if too large, may report nonexistent cycles
int soundmode = LINEARMODE;

cout << "\nThe interesting things happen from about 3.2 to 4.0" << endl;
cout << "To capture screens, run under Windows and PrtSc to save a screen." << endl;
cout << endl;
cout << "During display:\n";
cout << "B       toggles sound\n";
cout << "C       Sound is CHROMATIC\n";
cout << "L       Sound is raw LINEAR frequency\n";
cout << "S       Sound is restricted to a major SCALE\n";
cout << "P       toggles pause and beep when a cycle is found\n";
cout << "<Space> pauses display\n";
cout << "<ESC>   quits.\n";

cout << "\nEnter lower bound (0 to 4): ";
cin >> lobound;
cout << "Enter upper bound (" << lobound << " to 4): ";
cin >> hibound;
do
{
	cout << "\nModes: <W>hole bif diagram, or <G>raph for each R value\n";
	cout << "Enter mode: ";
	bifmode = tolower(getche());
}
while(!strchr("wg",bifmode));
if(bifmode == 'w')
{
	cout << "\nThe duplicate limit also limits the cycle size you can catch...\n";
	cout << "Move to next stripe after how many duplicated points? ";
	cin >> maxdups;
}

initgraf();						// default is VGAHI
int maxx = getmaxx();
int maxy = getmaxy();
int maxcolor = getmaxcolor();

double step = (hibound - lobound) / (double)maxx;

if(bifmode == 'g')
	setcolor(WHITE);	// the color the lines will be drawn in

screenx = -1;			// -1 because incremented at loop start below
						// r seldom ends up at hibound, but did once.  probably
						// because can't trust using double math for a loop,
						// but also possible I'm miscounting needed loop passes.
char buf[80];
double x;
for(double r = lobound ; r <= hibound ; r += step)
{
	if(bifmode == 'g')					// for graph mode, clear screen
	{
		sleep(1);						// in g-mode, sleep after (before) each screen
		if(kbhit() && (getch() == ' '))	// pause until user types a char
			getch();
		clearviewport();				// before each new stripe
	}
	if(bifmode == 'w')					// in whole mode, each stripe increments screenx
		screenx++;

	ostrstream os(buf,sizeof(buf));
	os << "r=" << r << " of " << lobound << " to " << hibound << ", step=" << step << ends;
	gputs(1,1,LIGHTGRAY,buf);

	x = .5;
	for(int i = 0 ; i < 50 ; i++)		// allow equation to settle down
		x = (r * x) - (r * x * x);

	double refpoint;					// used to determine cycle length
	BOOL firstpass = TRUE;			   	// whether first pass through loop
	int dupcount = 0;		   			// how many pixels are already set
	int cyclecount = 0;		   			// 3-cycle, etc.
	while(1)							// this loop plots a stripe.  exits if
	{									// cycle found, too many dups, or user quits
		x = (r * x) - (r * x * x);
		screeny = maxy - (int)(x * (double)maxy);		// invert to display
		if(beepon)
		{
			uint freq;
			switch(soundmode)
			{
				case CHROMATICMODE:
					freq = scale.GetFreq(scale.TranslateToNote(x,0,1));
					break;
				case MAJORSCALEMODE:
					freq = scale.GetFreq(scale.TranslateToScaleNote(x,0,1));
					break;
				case LINEARMODE:  	// this is still the best
				default:
					freq = scale.TranslateToSound(x,0,1); // will be 50 to 2550 Hz.
					break;
			}
			sound(freq);
			delay(100);		// 100 seems best for normal use, but others are interesting
		}
		if(firstpass)
		{
			refpoint = x;		// save first x to test for repeating cycle
			if(bifmode == 'g')
			{
				screenx = 0;
//				moveto(screenx,screeny);    // see below, for using lines
			}
			firstpass = FALSE;
		}
		else					// if not first, do the cycle test
		{
			if(bifmode == 'g')			// in graph mode, only
				if(++screenx > maxx)	// plot 640 points, then move on.
					break;
			cyclecount++;
			if(fabs(x - refpoint) <= mindiff)
			{
				ostrstream os(buf,sizeof(buf));
				os << setw(5) << cyclecount << "-cycle" << ends;
				gputs(1,3,LIGHTGRAY,buf);
				if(pause)
				{
					putchar(7);			// beep
					sleep(1);			// pause
				}
				break;		// if cycling, no need to plot more points
			}
		}
		if(bifmode == 'w')
		{
			color = getpixel(screenx,screeny);
			if(color)		// if maxdups points are dups, move on to next stripe
				if(++dupcount == maxdups)
					break;
			color = min(color+1,maxcolor);		// increase color w/each hit
		}
		else
			color = WHITE;
// 		if(bifmode == 'g')
//     		lineto(screenx,screeny);	// optional: connect points with lines
//         else
			putpixel(screenx,screeny,color);

		if(kbhit())                	// user input
			switch(tolower(getch()))
			{
				case 27:            		// quit
					nosound();
					closegraph();
					return(0);
				case 'b':            		// toggle beep
					nosound();
					beepon = !beepon;
					break;
				case 'p':            		// toggle delay
					pause = !pause;
					break;
				case 'c':                  	// set soundmode
					soundmode = CHROMATICMODE;
					beepon = TRUE;
					break;
				case 'l':            		// set soundmode
					soundmode = LINEARMODE;
					beepon = TRUE;
					break;
				case 's':            		// set soundmode
					soundmode = MAJORSCALEMODE;
					beepon = TRUE;
					break;
				case ' ':           		// pause display
					getch();
					break;
			}
	}			// end while(1)   (plot all the points in a stripe)
}				// end for r = lobound to hibound
nosound();
getch();
closegraph();
return(0);
}				// end main()

 

 

Valid HTML 4.01 Transitional Valid CSS
View content labeling at ICRA.
Copyright ©2007 Steven Whitney. Last modified 09/25/2007.