import ChaosDemos.*;
import java.awt.*;
import java.util.*;
import java.net.URL;
import graph.*;
/**
* Iterates and plots various 2D maps
* Uses the "Java Graph Class Library" by Leigh Brookshaw
* @version 3 August, 1997
* @author Michael Cross
*/
public class Control extends dynamicGraph {
/** run check box number */
private int r;
/** number of curves */
private int ncurve=-1;
/** index of first data curve */
private int ncurve0;
/** index of data curve for points near periodic orbit */
private int ncurve1;
/** index of data curve for points near periodic orbit */
private int ncurve2;
/** number of iterations to eliminate transient */
private int ntrans =0;
/** accumulated number of iterations */
private int iterations;
/** accumulated number of points plotted */
private int plotted;
/** number of iterations to do before plotting */
private int jump=1;
/** function chosen: 0=HENON 1=DUFFING 2=BAKERS 3=YORKE
4=SINAI 5=MYFUNCTION */
private int function=0;
/** number of variabels controlled by sliders */
private int nSliders;
/** number of data points accumulated in plotData */
private int nData=0;
/** Index for variable plotted on x-axis */
private int index0;
/** Index for variable plotted on y-axis */
private int index1;
/** fixed point number for control */
private int fpNumber;
/** index of periodic point controlled to */
private int flag;
/** control variable */
private int controlVariable;
/** Period of orbit */
int period=4;
/** Number of points needed before fit */
int fitNumber=10;
/** default delay for movie */
private int delayValue=7;
/** true after first mouse click */
private boolean clicked=false;
/** true on new run */
private boolean newRun;
/** true if found first periodic orbit */
private boolean foundFirst;
/** true if found other periodic orbit */
private boolean foundFirstOther;
/** true if fit to first periodic orbit */
private boolean fitFirst;
/** true of control cycle */
private boolean control;
/** iteration variable */
private double[] x={0.,0.,0.,0.};
/** iteration of periodic point */
private double[] xp={0.,0.,0.,0.};
/** mouse position */
private double[] xmouse={0.,0.};
/** map parameter */
private double a;
/** change in map parameter */
private double dp;
/** map parameter */
private double b;
/** map parameter */
private double c;
/** parameter increment */
private double change=0.01;
/** plot ranges */
private double xRange,yRange;
/** reciprocal of plot ranges */
private double xReduce,yReduce;
/** map parameters a,b,c */
private double[] params={1.4,0.3,0.};
/** save map parameters a,b,c */
private double[] paramSave={1.4,0.3,0.};
/** tolerances for periodic orbit search */
private double eps1,eps2;
/** starting value of x */
private double[] x0={0.,0.};
/** bottom-left corner */
private double[] cmin={-1.,-1.};
/** top-right corner */
private double[] cmax={1.,1.};
/** size of marker to be plotted */
private double marker=0.;
/** data for plotting */
private double[] moredata;
private double[] moredata1;
private double[] moredata2;
private double[] fixedPointData;
private double[] fixedPoints;
/** periodic points and linearization */
private double[][][] fp;
private double[] eig1;
private double[] eig2;
private double[][] ev1;
private double[][] ev2;
private double[][] fv1;
private double[][] fv2;
private double[] pm;
private boolean[] fitPoint;
private double[][] dfpdp;
private int[] offset;
private String blank=" ";
/** axis labesl */
private String[] axisLabel={" X "," Y "};
/** GUI elements */
private textControls variables;
private sliderControls parameters;
private buttonControls buttons;
private Choice functionChoice;
private CheckboxGroup cbg ;
private Checkbox[] cb;
private TextField periodBox;
private TextArea status;
/** classes used */
private superGraph2D graph;
private movie theMovie;
private Map2DFunction mapFunction;
private periodicOrbits PO;
/** parent */
private startControl outerparent;
/** animation thread */
private Thread aThread=null;
/** for location of marker.txt */
private URL markerURL;
/** location of marker.txt */
URL documentBase;
/** functions */
private static final int HENON=0;
private static final int DUFFING=1;
private static final int BAKERS=2;
private static final int YORKE=3;
private static final int SINAI=4;
private static final int MYFUNCTION=5;
/* log e -> log 10 */
private static final double le=0.43429;
/* log e -> log 2 */
private static final double l2=1.4427;
/** maximum number of points to be appended to plot */
private static int MAX_APPEND=1024;
/** maximum number of attempts to find good initial condition */
private static int MAX_TRY=1024;
/** value for testing divergence of iteration */
private static double MAX_VALUE = 100.;
/* arrays for setting parameters based on function choice */
int nParameters;
/**
* @param target starting class
* @see startControl
*/
public Control(startControl target, URL in_documentBase) {
documentBase=in_documentBase;
graph = new superGraph2D(this);
moredata = new double[2*jump];
moredata1 = new double[4*jump];
moredata2 = new double[2*jump];
fixedPointData = new double[4];
/*
** Load a file containing Marker definitions
*/
try {
markerURL = new URL(documentBase,"marker.txt");
graph.setMarkers(new Markers(markerURL));
} catch(Exception e) {
System.out.println("Failed to create Marker URL!");
}
theMovie = new movie(this);
this.outerparent = target;
addNotify();
setBackground(Color.lightGray);
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill=GridBagConstraints.BOTH;
setLayout(gridbag);
graph.borderRight=35;
graph.borderTop=80; // MCC 8-10
Panel leftPanel = new Panel();
leftPanel.setLayout(new BorderLayout());
constraints.gridheight = 1;
constraints.gridwidth=1;
constraints.weightx=0.75;
constraints.weighty = 1.0;
constraints.insets = new Insets(10,0,10,0);
gridbag.setConstraints(leftPanel, constraints);
add(leftPanel);
leftPanel.add("Center",graph);
Panel bottomLeftPanel = new Panel();
bottomLeftPanel.setLayout( new GridLayout(2,1));
bottomLeftPanel.add(theMovie);
theMovie.borderBottom=0;
String[] buttonLabels={" Reset "," Clear ",
" Start "," Stop "};
buttons = new buttonControls((dynamicGraph) this,
buttonLabels,buttonLabels.length, true);
buttons.b_init[0] = true;
buttons.b_stopped[3] = false;
buttons.b_started[1] = true;
buttons.b_started[3] = true;
buttons.setup();
bottomLeftPanel.add(buttons);
leftPanel.add("South",bottomLeftPanel);
Panel rightPanel = new Panel();
rightPanel.setLayout(new BorderLayout());
Panel topRightPanel = new Panel();
topRightPanel.setLayout(gridbag);
rightPanel.add("Center",topRightPanel);
nSliders = params.length;
String[] textboxes = new String[nSliders];
for (int i=0;i
* (May fail under Windows95)
*/
//************************************************************************
public boolean handleEvent(Event evt) {
switch (evt.id) {
case Event.WINDOW_DESTROY:
movieStop();
outerparent.hideWindow();
return super.handleEvent(evt);
case Event.WINDOW_ICONIFY:
movieStop();
buttons.enableGo();
enableAll();
return super.handleEvent(evt);
case Event.ACTION_EVENT:
if(evt.target == functionChoice) {
function = functionChoice.getSelectedIndex();
setDefaults();
updateParameters();
updateVariables();
if(randomInitialCondition()) restart();
status.appendText("\nHit START to find periodic points");
return super.handleEvent(evt);
}
else if(evt.target == cb[0]) {
for(int i=0;i<4;i++)
parameters.enable(i);
cb[1].disable();
cb[2].disable();
cb[3].disable();
stopMovie();
periodBox.enable();
status.appendText(blank);
status.appendText("\nFind periodic points");
return super.handleEvent(evt);
}
else if(evt.target == cb[1]) {
for(int i=0;i<4;i++)
parameters.disable(i);
cb[2].disable();
cb[3].disable();
stopMovie();
functionChoice.disable();
periodBox.disable();
status.appendText(blank);
status.appendText("\nFind periodic points for p - dp");
return super.handleEvent(evt);
}
else if(evt.target == cb[2]) {
for(int i=0;i<4;i++)
parameters.disable(i);
cb[3].disable();
cb[1].disable();
stopMovie();
functionChoice.disable();
periodBox.disable();
status.appendText(blank);
status.appendText("\nFind periodic points for p + dp");
return super.handleEvent(evt);
}
else if(evt.target == cb[3]) {
parameters.enable(3);
cb[1].disable();
cb[2].disable();
stopMovie();
functionChoice.disable();
periodBox.disable();
// status.appendText("\nSeeking control...");
offset[1]=findOffset(fp[0],fp[1]);
offset[2]=findOffset(fp[0],fp[2]);
for(int i=0;i=0) ncurve = graph.deleteAllCurves();
clicked=false;
newRun=true;
index0=0;
index1=1;
iterations=0;
plotted=0;
mapFunction.winding=0;
mapFunction.total=0;
data1[0]=0;
data1[1]=0;
data1[2]=1;
data1[3]=1;
ncurve = graph.addCurve(data1,2,Color.lightGray,0,7,0.5);
data2[0]=scaleX(x[index0]);
data2[1]=scaleY(x[index1]);
if(marker<=0.01){
markerType=7;
markerScale=1.;
}
else {
markerType=1;
markerScale=marker;
}
ncurve = graph.addCurve(data2,1,Color.blue,0,markerType,markerScale);
ncurve0=ncurve;
if(control) {
for(i=0;i=0 && fitPoint[fpNumber]) {
if(inBounds==1) {
// dp=pm[fpNumber]*((x[0]-fp[0][fpNumber][0])*fv1[fpNumber][0]
// +(x[1]-fp[0][fpNumber][1])*fv1[fpNumber][1]);
// System.out.println(flag+" dp= "+dp);
// if(Math.abs(dp)=0)
if(period > 1) status.appendText("\nControlled to point "+flag+" dp: "+(float)dp);
else status.appendText("\ndp: "+(float)dp);
if(Math.abs(dp)=0) {
flag=-1;
// status.setText(blank);
status.appendText("\nSeeking control...");
theMovie.setScrollValue(delayValue);
}
}
}
else {
foundOrbit=PO.testPoint(x);
if(foundOrbit==1) {
if(inBounds == 1) {
moredata1[nplot1++]=scaleX(x[index0]);
moredata1[nplot1++]=scaleY(x[index1]);
moredata1[nplot1++]=scaleX(x[index0+2]);
moredata1[nplot1++]=scaleY(x[index1+2]);
n1=n1+2;
if(!foundFirst) {
ncurve = graph.addCurve(moredata1,2,Color.red,0,1,1.0);
ncurve1=ncurve;
// System.out.println("Added periodic curve");
nplot1=0;
n1=0;
foundFirst=true;
}
}
for(i=0;i MAX_APPEND) break;
// if(n1 > MAX_APPEND) break;
// if(n2 > MAX_APPEND) break;
graph.paintAll=false; // Don't paint while updating data
if(n>0) graph.appendToCurve(moredata,n,ncurve0);
if(n1>0) graph.appendToCurve(moredata1,n1,ncurve1);
if(n2>0) graph.appendToCurve(moredata2,n2,ncurve2);
graph.paintAll=true;
graph.clearAll=false;
graph.repaint();
plotted=plotted+n;
return true;
}
//**********************************************************************
/**
* Stop thread and close fit window
*/
//**********************************************************************
public void stop() {
movieStop();
enableAll();
buttons.enableGo();
}
//**********************************************************************
/**
* Respond to buttonControls
* @see buttonControls
* @param buttonIndex index of button pushed
*/
//**********************************************************************
public void respondToButtons(int buttonIndex) {
if(buttonIndex==0) {
// setDefaults();
updateParameters();
updateVariables();
if(randomInitialCondition()) {
restart();
buttons.enableGo();
}
}
else if(buttonIndex==1) {
graph.clearAll=false;
if(aThread != null) {
movieStop();
if(initialCondition(x)) {
restart();
newRun=false;
movieStart();
}
}
else {
updateVariables();
boolean dummy=randomInitialCondition();
restart();
}
}
else if(buttonIndex==2) {
if(clicked) {
clicked=false;
x[0]=xmouse[0];
x[1]=xmouse[1];
x[2]=x[0];
x[3]=x[1];
if (!initialCondition(x)) return;
}
else {
if(!newRun) {
if (!randomInitialCondition()) return;
}
else newRun=false;
}
buttons.disableGo();
disableAll();
mapFunction.windingAdd=1;
graph.allowDrag=false;
movieStart();
}
else if(buttonIndex==3) {
mapFunction.windingAdd=0;
buttons.enableGo();
movieStop();
graph.allowDrag=true;
enableAll();
}
}
//*********************************************
/**
* Checks that x is within bounds cmin, cmax
* @param input value
* @return -1 if "diverges" set by MAX_VALUE, 0 if within bounds,
* 1 if outside bounds
*/
//*********************************************
private int checkBounds(double[] x) {
if(Math.abs(x[index0]) > MAX_VALUE || Math.abs(x[index1]) > MAX_VALUE) {
return -1;
}
if(x[index0] < cmin[0] || x[index0] > cmax[0] ||
x[index1] < cmin[1] || x[index1] > cmax[1])
return 0;
else return 1;
}
//**********************************************************************
/**
* Picks random intial condition, eliminates transient and test for
* divergences. Returns true if valid, false if cannot find a valid i.c.
* in MAX_TRY attempts.
* @return true if valid starting point found
*/
//**********************************************************************
private boolean randomInitialCondition() {
boolean diverged=true;
int nTry=0;
while(diverged && nTry < MAX_TRY) {
nTry++;
diverged = false;
x[0]=cmin[0]+Math.random()*(cmax[0]-cmin[0]);
x[1]=cmin[1]+Math.random()*(cmax[1]-cmin[1]);
if(ntrans>0) {
for(int i=0;i0) {
for(int i=0;i1) {
parameters.enable(1);
parameters.setText(1,String.valueOf(mapFunction.aDefault[1]));
}
else {
parameters.setText(1,"");
parameters.disable(1);
}
if(nParameters>2) {
parameters.enable(2);
parameters.setText(2,String.valueOf(mapFunction.aDefault[2]));
}
else {
parameters.setText(2,"");
parameters.disable(2);
}
}
//**********************************************************************
/**
* Adds to graph
* @param g Graphics context
* @param r data rectangle of graph
*/
//**********************************************************************
public void addToGraph( Graphics g, Rectangle r) {
}
//**********************************************************************
/**
* Sets axes defaults based on type of plot
*/
//**********************************************************************
public void setAxesDefaults() {
variables.setText(0,String.valueOf(mapFunction.xminDefault));
variables.setText(1,String.valueOf(mapFunction.yminDefault));
variables.setText(2,String.valueOf(mapFunction.xmaxDefault));
variables.setText(3,String.valueOf(mapFunction.ymaxDefault));
graph.setXAxisTitle("X");
graph.setYAxisTitle("Y");
}
private double scaleX(double inX) {
return (inX-cmin[0])*xReduce;
}
private double scaleY(double inY) {
return (inY-cmin[1])*yReduce;
}
private void plotPeriodicPoint(int i) {
int j,ifp;
double mult1,mult2;
mult1=checkVector(PO.fp[i],PO.ev1[i]);
mult2=checkVector(PO.fp[i],PO.ev2[i]);
if(mult20) ncurve=graph.addCurve(fixedPoints,ifp,Color.black,0,1,2.0);
}
private double checkVector(double[] p, double[] v) {
double mult=1.;
int nib=0;
double[] xt=new double[2];
while(nib<2) {
mult=mult/2.;
nib=0;
xt[0]=p[0]+mult*v[0];
xt[1]=p[1]+mult*v[1];
nib=nib+checkBounds(xt);
xt[0]=p[0]-mult*v[0];
xt[1]=p[1]-mult*v[1];
nib=nib+checkBounds(xt);
}
return mult;
}
private void plotVector(double[] p, double[] v, double mult, Color c) {
double[] data=new double[4];
data[0]=scaleX(p[0]+mult*v[0]);
data[1]=scaleY(p[1]+mult*v[1]);
data[2]=scaleX(p[0]-mult*v[0]);
data[3]=scaleY(p[1]-mult*v[1]);
ncurve=graph.addCurve(data,2,c);
graph.repaint();
}
private int modplus(int i1, int i2, int i3) {
int result;
result=i1+i2;
while(result >= i3)
result=result-i3;
return result;
}
private int findOffset(double[][] p1, double[][] p2) {
double dist,minDist;
int i,j,k,offset;
minDist=1.e6;
offset=0;
for(i=0;i0) && !positive)) {
t.setText(String.valueOf(i));
// if(positive) alert = new alertDialog(this,"Must be positive");
// else alert = new alertDialog(this,"Must be negative");
return i;
}
return iNew;
}
private double dist(double[] p1, double[] p2) {
return Math.abs(p1[0]-p2[0])+Math.abs(p1[1]-p2[1]);
}
private int nearFixedPoint(double[] x) {
int i;
for(i=0;i