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