A program I wrote while at Summer Ventures of Science and Math to generate the bifurcation diagram. You can zoom in on portions of the diagram to see the self-similarity.

read more

Plotter.java

			
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class Plotter extends JFrame implements MouseListener,
		MouseMotionListener, ActionListener {
	int dotSize = 1;
	int xPixDragged;
	int yPixDragged;
	int prevMouseXCoord;
	int prevMouseYCoord;
	boolean dragging;
	int counter = 0;
	double xMin;
	double xMax;
	double yMin;
	double yMax;
	public JPanel resetPanel = new JPanel(); //Adds an instance of the JPanel class: created below
	public JButton resetButton = new JButton("Reset view");
	public PlotPanel plotPanel = new PlotPanel();
	int oldMouseX;
	int oldMouseY;
	boolean axesVisible;
	int numOfPoints;
	double[] xCoords;
	double[] yCoords;
	boolean hasPoints = false;

	public Plotter() {  // this is the default constructor for Plotter -- it creates an instance of Plotter
		setTitle("Point Plotter"); //This sets to the default object, that object is Plotter in this case
		setSize(10000, 10000); //Sets the bounds of the window
		add(resetPanel, BorderLayout.SOUTH);//Introduces the JPanel to this method
		resetPanel.add(resetButton);//Adds the created JButton
		resetButton.addActionListener(this);//Adds an action listener to the button
		add(plotPanel);//This refers to the default object
		plotPanel.addMouseListener(this);
		plotPanel.addMouseMotionListener(this);
		setLocationRelativeTo(null);
	}

	public void setCoordinateBounds(double xmin, double xmax, double ymin,
			double ymax) {

		xMin = xmin;
		xMax = xmax;
		yMin = ymin;
		yMax = ymax;
		repaint();

	}

	public void setAxesVisible(boolean vis) {
		axesVisible = vis;
		repaint();
	}

	public void setPointSet(double[] xc, double[] yc) {
		xCoords = xc;
		yCoords = yc;
		numOfPoints = xc.length;
		hasPoints = true;
		repaint();
	}

	public int getYPixCoord(double yCoord) {
		return (int) (getHeight() - ((yCoord - yMin) * getHeight() / (yMax - yMin)));
	}

	public int getXPixCoord(double xCoord) {
		return (int) ((xCoord - xMin) * getHeight() / (xMax - xMin));
	}

	public double getXCoord(int xPixCoord) {
		return xMin + (xPixCoord) * (xMax - xMin) / getWidth();
	}

	public double getYCoord(int yPixCoord) {
		return yMax - (yPixCoord) * (yMax - yMin) / getHeight();
	}
	
	@Override
	public void actionPerformed(ActionEvent event) {
		setCoordinateBounds(1, 5, 0, 1);
	}

	@Override
	public void mouseDragged(MouseEvent event) {
		counter++;
		int mouseX = event.getX();
		int mouseY = event.getY();

		double xInc = getXCoord(mouseX) - getXCoord(oldMouseX);
		double yInc = getYCoord(mouseY) - getYCoord(oldMouseY);
		// System.out.println("'real' coord of the mouse was:("+getXCoord(mouseX)+","+getYCoord(mouseY)+")");
		xMax -= xInc;
		xMin -= xInc;
		yMin -= yInc;
		yMax -= yInc;
		if (counter == 2) {
			// System.out.println("Updating the display");
			counter = 0;
			repaint();
		}

		oldMouseX = mouseX;
		oldMouseY = mouseY;

	}

	@Override
	public void mouseMoved(MouseEvent e) {
		int mouseX = e.getX();
		int mouseY = e.getY();
		oldMouseX = mouseX;
		oldMouseY = mouseY; 

	}

	public class PlotPanel extends JPanel { //Creates a class
		public void paintComponent(Graphics g) {
			if (hasPoints) {

				if (axesVisible) {
					g.drawLine(0, getYPixCoord(0), getWidth(), getYPixCoord(0));
					g.drawLine(getXPixCoord(0), 0, getXPixCoord(0), getHeight());
				}
				for (int i = 0; i < xCoords.length; i++) {
					int pixX = getXPixCoord(xCoords[i]);
					int pixY = getYPixCoord(yCoords[i]);
					if (pixX >= 0 && pixY >= 0 && pixX < getWidth()
							&& pixY < getHeight()) {
						g.fillRect(pixX, pixY, dotSize, dotSize);
					}
				}
			}
		}
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed(MouseEvent e) {
		System.out.println("Mouse event was :" + e.getModifiers());
		if (e.getModifiers() == 4) {
			zoomIn(getXCoord(e.getX()), getYCoord(e.getY()));
		}

	}

	public void zoomIn(double x, double y) {
		double wid = xMax - xMin;
		double hei = yMax - yMin;
		setCoordinateBounds(x - wid / 4, x + wid / 4, y - hei / 4, y + hei / 4);
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub

	}
}

pointCreater.java

			
import java.util.Scanner;

import javax.swing.JSlider;

public class pointCreater {

	/**
	 * I have an idea, what about taking the derivative of the entire
	 * Bifurcation Diagram? Never mind. Possible reason for "The Beast," it's
	 * likely to do with the precision of the "observable" condition, when
	 * altered, the regular bifurcation diagram returns :(.
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scan = new Scanner(System.in);
		StringBuilder result = new StringBuilder();
		System.out.println("Enter a starting x value");
		double xStart = scan.nextDouble();
		int pointCount = 0;
		double y = 0;
		int f = 0;
		double y2 = 0;
		double y4 = 0;
		double y6 = 0;
		double y8 = 0;
		int r = 0;
		double y1 = 0;
		int arrayBounds = 3000000;
		double[] xCoords = new double[arrayBounds];
		double[] yCoords = new double[arrayBounds];
		boolean convergenceForK = false;
		boolean chaos = false;
		double x;
		Plotter plot = new Plotter();
		plot.setVisible(true);
		plot.setCoordinateBounds(1, 5, 0, 1);
		for (double k = 1.01; k < 5; k += .001) { // Varies the K constant in
													// the equation

			// System.out.println("K=" + k);
			y1 = 567444;
			y2 = 456;
			y4 = 4235;
			x = xStart;
			for (int a = 0; a < 100; a++) { // Iterates the function many times
				y = k * (x - (x * x));
				// System.out.println("Y=" + y);
				convergenceForK = false;
				chaos = false; // Resets the chaos value in case it was
								// previously true
				
				if (Math.abs(y - y1) < .000001 || Math.abs(y - y2) < .000001
						|| Math.abs(y - y4) < .000001
						|| Math.abs(y - y6) < .000001
						|| Math.abs(y - y8) < .000001) {
					// Checks to see if
					// consecutive values of
					// outputs are close,
					// also values skipping
					// an output, skipping 3
					// outputs, etc.
					convergenceForK = true;// if any pattern is found it jumps
											// jumps to plotting the points
					a = 300; // it stops the iteration
				}

					if (Math.abs(y - y1) > .00000001
							&& Math.abs(y - y2) > .00000001
							&& Math.abs(y - y4) > .00000001
							&& Math.abs(y - y6) > .00000001
							&& Math.abs(y - y8) > .00000001) {

						chaos = true; // If no pattern is found, it jumps
						
					}

				
				y1 = y;
				if (a % 2 == 0) {
					y2 = y;
				}
				if (a % 4 == 0) {
					y4 = y;
				}
				if (a % 6 == 0) {
					y6 = y;

				}
				if (a % 8 == 0) {
					y8 = y;
				}

				x = y;
			}
			r = 0;
			if (convergenceForK) {

				while (r < 1) {

					y = k * (x - (x * x));
					xCoords[pointCount] = k; // Now for each of the numerous
												// outputs
					yCoords[pointCount] = y;
					// System.out.println("X coord:" + k + "       Y coord:" +
					// y);
					pointCount++;
					x = y;
					r++;
				}
			}
			if (chaos) {
				f += 1;
				while (r < 500) {
					y = k * (x - (x * x));

					xCoords[pointCount] = k;
					yCoords[pointCount] = y;
					// System.out.println("X coord:" + k + "       Y coord:" +
					// y);
					pointCount++;
					x = y;
					r++;
					
				}
			}

		}
		plot.setPointSet(xCoords, yCoords);

		System.out.println("F=" + f);
	}

}

varyingKValues.java

			
import java.util.Scanner;
import java.applet.Applet;
import java.awt.*;
import java.util.*;
public class varyingKValues   {

	/** Experiment further between 3.21 & 3.4
	 * Starting K Value of .13
	 * y=k(x-x^2)
	 * It appears as though period doubling occurs to a very minor degree at most, if not all k values. As k grows, so does the 
	 * magnitude of the period doubling. Paradoxically, as each iteration continues, the period doubling (subsides/magnifies)?.
	 * Examples: k=2.5
	 * Period Doubling noted here:
	 * First Bifurcation: 2.85-2.89; Noticeable at 3.03.
	 * Strange split, not very definite, starts around 3.21. Visible at 3.4. 
	 * Second Bifurcation: 3.4735;  
	 * Could interdependence be going on? It appears as though these equations flow nicely, perhaps the y value of the previous 
	 * system determines both the x value of the next as well as the K value. 
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scan = new Scanner(System.in);
	    StringBuilder result = new StringBuilder();
		System.out.println("Enter a starting x value");
		double x = scan.nextDouble();
		double y = 0;
		for (int i = 50; i > 0; i--) {
			y = 1.1*(x-(x*x));
			
			System.out.print(x);
			System.out.print("     "+y+"    "+"23");
			System.out.println();
			x = y;
	}
	}}