|
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,
|
|
/* 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()
|
|
|
|
|
|