[Solved] How to debug this timeout error


#1

Conclusion: 10-15-2018
From what I’ve seen attempting to debug this and creating a hybrid version with an earlier boolean version there’s an issue with the classes function that causes the program to continuously load for a long time and finally give a black screen when the complex sets aren’t satisfying the proper condition. This issue is only present when an ‘add’ complex is utilized. I’ve attempted it with two types of ‘add’ classes (used in the original quaterion version and the one shown in the below code) with the same result, but the loading issue isn’t present when the complex is just built into the main complex equation as a single, four float complex.

Let me clarify, this is an amalgamation of two separate issues (1) the complex ‘add’ function in the class gets stuck in an extremely long load time when the complex ‘set’ values are altered in the class itself to influence the entire equation, and (2) the way this program is coded it throws the error when the program is slow to start.

I don’t know the specifics on the origins of the timeout error, but with the boolean version which doesn’t experience the timeout error the unending load time can be observed.


I’ve been working on some code for rendering the Buddhabrot with zoom capabilities and have a strange timeout problem.

I’ve improved the original Metropolis-Hastings Algorithm for zooming from a max of 64x to a max of over 256x-512x, among other changes…

ProsExplorer, Oct 2018
Changelog -

  • Centered axis’ to 0,0 ranges (producing the standard Buddhabrot)
  • Removed asynchronous functions in the program
  • Improved Metropolis-Hastings Algorithm to scale the range of orbital
    x,y random values to the current magnification range (zoom max 400+),
  • Corrected Z Multiplication Class to follow Quaternion Multiplication Rules
  • Eliminated void flushImage(),flushSources() redundancies
    and combined with void flushEstimates()
  • Removed the Quaternion HyperComplex Class completely and replaced it with
    the Binomial Complex class, for simplicity in attempt to eliminate timeout error
    when the equations are changed

Trouble is that even with the change from Quaternion HyperComplex calculations to the more simplistic Binomial Complex calculations in the classes the code continues to throw this error if the code takes any longer:

java.lang.RuntimeException: Waited 5000ms for: <72d584ca, 7c1274e0>[count 2, qsz 0, owner <main-FPSAWTAnimator#00-Timer0>] - <main-FPSAWTAnimator#00-Timer0-FPSAWTAnimator#00-Timer1>
	at processing.opengl.PSurfaceJOGL$2.run(PSurfaceJOGL.java:410)
	at java.lang.Thread.run(Thread.java:748)

With different versions of this same program, which doesn’t use classes for the calculations, the code could take as much time as needed to render the fractal array points, but for some reason this later version of the program can’t do the same. The code works fine, but once the calculations take more time it throws an error.

What’s causing this timeout error and how could I allow for more time?
After narrowing it down in the code, the error can easily be reproduced by placing “println(x1,y1)” into the line #308 of the iterate section.

      y1 = ( height - iy ) * (3.0) / height - 1.5;
        println(x1,y1)  // Line 308
      if( iterate0(x1,y1) > 1/15.0 ) {

The working Binomial Complex version:

//-------------------------------------------------------------------
// Buddhabrot
// Claudio Gonzales, April 2009
// Albuquerque, New Mexico

// Based on Code by J. Tarbell and algorithms by Alex Boswell
//-------------------------------------------------------------------

// ProsExplorer, Oct 2018

//Changelog -
// - Centered axis' to 0,0 ranges (producing the standard Buddhabrot)
// - Removed asynchronous functions in the program
// - Improved Metropolis-Hastings Algorithm to scale the range of orbital 
//    x,y random values to increase magnification range from 64x to 512x
// - Corrected Z Multiplication Class to follow Quaternion Multiplication Rules
// - Eliminated void flushImage(),flushSources() redundancies 
//    and combined with void flushEstimates()
// - Removed the Quaternion HyperComplex Class completely and replaced it with 
//   the Binomial Complex class, for simplicity in attempt to eliminate timeout error
//   when the equations are changed
//-------------------------------------------------------------------

int dim = 800;      // screen dimensions (square window)
int bailout = 2000; // number of iterations before bail ...... 4000, 200, 10 for Nebula
int plots = 10000;  // number of plots per frame
long iterations = 0;
float ratio;
float magnification = 1;
float zoomrate = 2;  
int time = 0;
int maximumExposures;
int maximumSources;

int gxMin = 0; 
int gyMin = 0;
int gxMax = dim;
int gyMax = dim;

float J = 0;
float K = 0;

float x = 0;
float y = 0;

int gX = 0, gY = 0;  //Global real and imaginary counters

float xMin = -2.0;
float xMax = 2.0;
float yMin = -2.0;
float yMax = 2.0;

boolean escape, allow = true, first = true, hotspots = false, cycle = false, saved = false;
int[][] exposures = new int[dim][dim];
int[][] points = new int[dim][dim];
int[][] sources = new int[dim][dim];
PFont metaBold;
PImage temp;
color c;

//  MAIN ----------------------------------------------------------------

void setup() { 
  
  //size(540,540,P3D);  //Original Dimensions
  size(800,800,P3D);    //Normal code
  background(0);
  frameRate(15);
  smooth();

  flushEstimates();
  Analyze();

}

void draw() {
  
    plotOrbits();
    time++;  
    
    if( time%30==1 && hotspots ) {
      // show progress...
      if( cycle ) {
        trimGrid();
      }
      drawSources(false);
      allow = true;
      first = true;
    }
    else if( time%30== 1 ) {
      if( cycle ) {
        trimGrid();
      }
      maximumSources = maxExposure( sources );  
      drawBuddha(false);
      allow = true;
    }  
    
    if( saved == true ) {
      fill(255);
      stroke(255);
      text("Saved!", width-50, 20);
      saved = false;
    }
}

void drawBuddha( boolean saveIt ) {
  maximumExposures = maxExposure( exposures );
  renderImage();
  
  if( saveIt ) {
    save("Buddhabrot.png");
  }
  
  fill( 255 );
  text("Bailout:  " + bailout, 5, 20);
  text("Iterations:  " + iterations, 5, 40);
  text("Image Center: " + (xMax+xMin)/2 + " + " + (yMax+yMin)/2 + "i + " + J + "j + " + K + "k", 5, 60);
  text("Image Width:  " + (xMax-xMin), 5, 80);
  text("Image Zoom:  " + magnification, 5, 100);
  text("Click left to zoom in.", 5, height-70);
  text("Click right to zoom out.", 5, height-50);  
  text("Click left and hold <shift> to save with data.", 5, height-30);
  text("Click right and hold <shift> to save raw image.", 5, height-10);
}

void drawSources( boolean saveIt ) {
  float R;
  maximumSources = maxExposure( sources );
  for( int ix = 0; ix <= width-1; ix++ ) {
    for( int iy = 0; iy <= height-1; iy++ ) {
      R = float(sources[ix][iy]) / float(maximumSources);
      c = color( 255*R );
      set(ix,iy,c);
    }
  }
  stroke(255);
  line(gxMin,0,gxMin,height);
  line(gxMax,0,gxMax,height);
  line(0,gyMin,width,gyMin);
  line(0,gyMax,width,gyMax);
  
  if( saveIt ) {
    save("Sources.png");
  }
  
  fill( 0 );
  text("Bailout:  " + bailout, 8, 23);
  text("Iterations:  " + iterations, 8, 43);
  text("Image Center: " + (xMax+xMin)/2 + " + " + (yMax+yMin)/2 + "i + " + J + "j + " + K + "k", 8, 63);
  text("Image Width:  " + (xMax-xMin), 8, 83);
  text("Image Zoom:  " + magnification, 8, 103);
  text("Press enter to return to your buddhabrot.", 8, height-47);
  text("Click left and hold <shift> to save with data.", 8, height-27);
  text("Click right and hold <shift> to save raw image.", 8, height-7);
  fill( 255 );
  text("Bailout:  " + bailout, 5, 20);
  text("Iterations:  " + iterations, 5, 40);
  text("Image Center: " + (xMax+xMin)/2 + " + " + (yMax+yMin)/2 + "i + " + J + "j + " + K + "k", 5, 60);
  text("Image Width:  " + (xMax-xMin), 5, 80);
  text("Image Zoom:  " + magnification, 5, 100);
  text("Press enter to return to your buddhabrot.", 5, height-50);
  text("Click left and hold <shift> to save with data.", 5, height-30);
  text("Click right and hold <shift> to save raw image.", 5, height-10);
}


//  Interface Section ----------------------------------------------------------------

void keyPressed() {  
    if( key == ENTER || key == RETURN ) {
      if( hotspots ) { hotspots = false; drawBuddha(false); }
      else { hotspots = true; }
    }
    if ( hotspots ) {
      drawSources(false);
    }
    else {
      drawBuddha(false);
    }
}
void mousePressed() {
    if( hotspots ) {
      fill(255);
      if ( mouseButton == LEFT ) {
        save("Sources.png");
        saved = true;
      }
      else {
        drawSources(true);
        saved = true;
      }
    }
    else { 
      if ( mouseButton == LEFT && allow && keyPressed == true && keyCode == SHIFT ) {
        save("Fractal.png");
        cycle = false;
        stroke(255);
        saved = true;
      }
      else if ( mouseButton == RIGHT && allow && keyPressed == true && keyCode == SHIFT ) {
        drawBuddha(true);
        cycle = false;
        stroke(255);
        saved = true;
      } 
      else if ( mouseButton == LEFT ) {
        float NEWspan = (xMax-xMin) / zoomrate;
        x = mouseX * (xMax-xMin) / width + xMin;
        y = ( height - mouseY ) * (yMax-yMin) / height + yMin;
        xMax = x + NEWspan/2;
        xMin = x - NEWspan/2;
        yMax = y + NEWspan/2;
        yMin = y - NEWspan/2;
        iterations = 0;
        flushEstimates();
        renderImage();
        Analyze();
        allow = false;
        magnification *= zoomrate;
      }
      else {
        float NEWspan = (xMax-xMin) * zoomrate;
        x = mouseX * (xMax-xMin) / width + xMin;
        y = ( height - mouseY ) * (yMax-yMin) / height + yMin;
        xMax = x + NEWspan/2;
        xMin = x - NEWspan/2;
        yMax = y + NEWspan/2;
        yMin = y - NEWspan/2;
        iterations = 0;
        flushEstimates();
        renderImage();
        Analyze();
        allow = false;
        magnification /= zoomrate;
      }
    }
    if ( hotspots ) {
      drawSources(false);
    }
    else {
      drawBuddha(false);
    }
}

// Complex Class------------------------------------------------------
class Complex {
  public float real;
  public float img;

  Complex() {
    real = img = 0.0f;
  }

  public Complex(float x, float y) {
    super();
    this.real = x;
    this.img = y;
  }

  public void Set(float x0, float y0) {
    real = x0;
    img = y0;
  }

  public Complex add(Complex c) {
    real += c.real;
    img += c.img;
    return this;
  }

  public void mult(Complex c) {
    float nReal = real * c.real - img * c.img;
    float nImg = real * c.img + img * c.real;
    real = nReal;
    img = nImg;
  }

  public Complex squared() {
    float nReal = (real - img)*(real + img);
    float nImg = 2 * real * img;
    real = nReal;
    img = nImg;  
    return this;
  }

  public float sizeSquared() {
    return real * real + img * img;
  }
}

// Iterate------------------------------------------------------------

void Analyze() {
  Complex c = new Complex(0,0);
  Complex z = new Complex(0,0);
  float x1;
  float y1;
  gxMin = 0;
  gyMin = 0;
  gxMax = width;
  gyMax = height;
  
  for(int ix = 0; ix < width; ix++ ) {
    for(int iy = 0; iy < height; iy++ ) {
      x1 = ix * (3.0) / width - 2.0;
      y1 = ( height - iy ) * (3.0) / height - 1.5;
        //println(x1,y1)  // Line 308
      if( iterate0(x1,y1) > 1/15.0 ) {
        z.Set(0,0);
        c.Set(x1,y1);
        for (int i=0; i<40; i++) {
          //Z = Z^2 + C:   
            z = z.squared().add(c);
          
          if( z.sizeSquared() > 10 ) {
             i = 41;
          }
          x1 = ( z.real - xMin ) * width / (xMax-xMin);
          y1 = height * ( 1 - ( z.img - yMin ) / (yMax-yMin) );
          if( int(x1) >= 0 && int(x1) < width && int(y1) >= 0 && int(y1) < height ) {
            points[ix][iy]++;
          }
        }
      }
    }
  }
  maximumSources = maxExposure(points);  
}


int iterate(float x0, float y0, boolean drawIt) {
  int ix,iy;
  Complex z = new Complex(0,0);
  Complex c = new Complex(x0,y0);

  for (int i=0; i<bailout; i++) {
  //Z = Z^2 + C:   
    z = z.squared().add(c);

    if (drawIt && (i > 3)) {
    iterations++;
      
      ix = int( ( z.real - xMin ) * width / (xMax-xMin) );
      iy = int( height * ( 1 - ( z.img - yMin ) / (yMax-yMin) ) );
      
        if( ix > 0 && ix < width && iy > 0 && iy < height ) {
          exposures[ix][iy]++;
        }
        
      iy = int( height * ( 1 - ( -z.img - yMin ) / (yMax-yMin) ) );
      
        if( ix > 0 && ix < width && iy > 0 && iy < height && K == 0 ) {
          exposures[ix][iy]++;
        }
        if( z.sizeSquared() > 10 ) {
          i = bailout+1;
        }
    }
      
    if ( z.sizeSquared() > 4 ) {
      return i;
    }
  }
  return -bailout;
}

float iterate0(float x0, float y0) {
  Complex z = new Complex(0,0);
  Complex c = new Complex(x0,y0);

  for (int i=0; i<75; i++) {
  //Z = Z^2 + C:   
    z = z.squared().add(c);
    
    if ( z.sizeSquared() > 4 && i > 4 ) {
      return i/75.0;
    }
  }
  return 0;
}


int iterateInWindow(float x0, float y0) {
  int ix,iy;
  int j = 0;
  Complex z = new Complex(0,0);
  Complex c = new Complex(x0,y0);

  for (int i=0; i<bailout; i++) {
  //Z = Z^2 + C:   
    z = z.squared().add(c);

    ix = int( ( z.real - xMin ) * width / (xMax-xMin) );
    iy = int( height * ( 1 - ( z.img - yMin ) / (yMax-yMin) ) );

      if( ix > 0 && ix < width && iy > 0 && iy < height ) {
        j++;
      }
      if ( z.sizeSquared() > 4 ) {
        return j;
      }
  }
  return -1;
}

void trimGrid() {
  
  gxMin = width;
  gyMin = height;
  gxMax = 0;
  gyMax = 0;
  float r;
  
  for(int ix = 0; ix < width; ix++ ) {
    for(int iy = 0; iy < height; iy++ ) {
      if( float(sources[ix][iy]) / float(maximumSources) > 0.075 ) {
        gxMin = min(gxMin,ix);
        gyMin = min(gyMin,iy);
        gxMax = max(gxMax,ix);
        gyMax = max(gyMax,iy);  
      }
    }
  }
  
}

// Probablility-------------------------------------------------------

Complex mutate(Complex z) {
  float r1, r2, phi, r, p;
  
  p = pow(0.2,abs(log(magnification)/log(zoomrate))+1);
  
  if (random(1) > 1-p ) {
    findCoordinate();
    return new Complex( x, y);
  } 
  else {
    r1 = ( 1 / magnification ) * 0.0001;
    r2 = ( 1 / magnification ) * 0.1;
    phi = random( 0, 1 ) *TWO_PI;
    r = r2* exp( -log( r2 / r1 ) * random( 0, 1 ) );
    return new Complex( z.real+r*cos(phi), z.img+r*sin(phi));
  }

}

float TransitionProbability( int n1, int n2 ) {
  return ( 1 - float(n1)/bailout ) / 
         ( 1 - float(n2)/bailout );
}

// Render-------------------------------------------------------------

void renderImage() {
  float mx = max( abs(xMin), abs(xMax) );
  float my = max( abs(yMin), abs(yMax) );
  float lx = min( abs(xMin), abs(xMax) );
  float ly = min( abs(yMin), abs(yMax) );

 for( int ix = 0; ix < width; ix++ ) {
    for( int iy = 0; iy < height; iy++ ) {
      ratio = float(exposures[ix][iy]) / float(maximumExposures);
      ratio = (atan(2*ratio-1)*4/PI+1)/2;
      //ratio = 1-abs(cos(ratio*PI));
      /*ratio = log( ratio * 1.71828184 + 1 );
      ratio = log( ratio * 1.71828184 + 1 );
      ratio = log( ratio * 1.71828184 + 1 );
      ratio = sq( ratio );*/
      
      //c = color( sin(sqrt(ratio)*PI)*255, sin((ratio)*PI)*255, sin(sq(ratio)*PI)*255 );
      c = color( sin(ratio*PI)*255, ratio*255, sqrt(ratio)*255  );
      //c = color( abs(sin(ratio*2*PI))*255, abs(sin(ratio*4*PI))*255, abs(sin(ratio*8*PI))*255 );
      //c = color( ratio*255 );
      
      set(ix,iy,c);
    }
  }
}

int maxExposure( int[][] Z ) {
  int maximum=0;
  for( int ix = 0; ix < width; ix++ ) {
    for( int iy = 0; iy < height; iy++ ) {
      maximum = max( maximum, Z[ix][iy] );
    }
  }
  return maximum;
}

void flushEstimates() {
  for( int i = 0; i < width; i++ ) {
    for( int j = 0; j < height; j++ ) {
      exposures[i][j] = 0;
         points[i][j] = 0;
        sources[i][j] = 0;
    }
  }
}

// plotOrbits---------------------------------------------------------

void plotOrbits() {

  float x0 = random(-2.0,2.0);
  float y0 = random(-2.0,2.0);
  
  int newt = 0;
  int newhits = 0; 
  int oldt = 0; 
  int oldhits = 0; 
  
  int x1;
  int y1;
  
  float t1, t2, Alpha;
  
  // iterate through some plots
  Complex c = new Complex( 0,0 );
  for (int n=0; n < plots; n++) {
    // Choose a random point in same range
    
    c = mutate( new Complex( x0, y0) );
    newt = iterateInWindow( c.real, c.img );
    newhits = newt;
    t1 = TransitionProbability(newt, oldt);
    t2 = TransitionProbability(oldt, newt);
    
    if (oldhits > 0) {
        Alpha = min(1, exp( log( (newhits * t1) ) - log( (oldhits * t2)) ) );
        if ( Alpha > random(1) ) {
            x0 = c.real;
            y0 = c.img;
            oldt = newt;
            oldhits = newhits;
        }
    } else {
        x0 = c.real;
        y0 = c.img;
        oldt = newt;
        oldhits = newhits;
    }

    oldhits = newhits;
    
    if( newt != -1 ) {
      newt = iterate( c.real, c.img, true);
      x1 = int( ( c.real + 2 ) * width / 3 );
      y1 = int( height * ( 1 - ( c.img + 1.5 ) / 3 ) );
      if( x1 >= 0 && x1 < width && y1 >= 0 && y1 < height ) {
        sources[x1][y1]++;
      }
      
    }
    
  }
}

void findCoordinate() {
  
  boolean leave = false;

  do {
    
    if( gX >= gxMax ) {
      gX = gxMin;
      gY++;
    }
    if( gY >= gyMax ) {
      gY = gyMin;
      cycle = true;
    }
    
    if( points[gX][gY] > 1 ) {
      leave = true;
      gX++;
    }
    
    gX++;
    
  } while( leave != true );
  
  
  x = gX * (3.0) / width + -2.0;
  y = ( height - gY ) * (3.0) / height + -1.5;
  
  //Scale random x,y ranges to magnification with Metropolis-Hastings Algorithm
    float r1 = ( 1 / magnification ) * 0.0001;
    float r2 = ( 1 / magnification ) * 0.1;
    float r = r2* exp( -log( r2 / r1 ) * random( 0, 1 ) );
   
    int rx;
    if (key == 'r') {
     rx = 1;
      if (rx>0){
      println(r);
      }
     }
    if (key == 'R') {
      rx = 0;
    }
    
  x += random( -0.02*r, 0.02*r );
  y += random( -0.02*r, 0.02*r );
  
}

//-------------------------------------------------------------------

Original, older code found here [https://www.openprocessing.org/sketch/7909]