• fullscreen
  • BML.pde
  • bml.pde
  • //Biham-Middleton-Levine Traffic Model in Processing
    //Adapted from the C version I posted on Wikipedia: http://en.wikipedia.org/wiki/User:Purpy_Pupple/BML
    
    boolean one=true;
    boolean two=false;
    int PERCENT=35;
    int H_SIZE=89;//height
    int W_SIZE=144;//width
    int cellSize=4;
    int [] statesone={0,0,0,0,1,1,2,2,2,1,1,1,0,1,1,2,2,2,0,0,0,0,1,1,2,2,2,};//secret sauce
    int [] statestwo={0,0,0,1,1,1,0,2,2,0,0,0,1,1,1,0,2,2,2,2,2,1,1,1,0,2,2,};//more secret sauce
    int [][] X = new int[H_SIZE][W_SIZE];//to store the current state before it is one's turn to move
    int [][] Y = new int[H_SIZE][W_SIZE];//to store the current state before it is two's turn to move
    boolean twoorone = one;
    
    int rand(){
      return (int)random(99999999);
    }
    
    void trafficroll(boolean oneortwo){
      //"rolls" traffic depending on whose turn it is.
      int a,b,c;//the value of the spot before, at, and after the position you're currently at.
      int mobility=0;//mobility
      if(oneortwo==one){
        for(int i=0;i<H_SIZE;i++){
          for(int j=0;j<W_SIZE;j++){
            a=X[(i-1+H_SIZE)%H_SIZE][j]; b=X[i][j]; c=X[(i+1)%H_SIZE][j];
            Y[i][j]=statesone[c+3*b+9*a];//awesome base three arithmetic!
            if(Y[i][j]>X[i][j]) mobility++;
          }
        }
      }else{
        for(int i=0;i<H_SIZE;i++){
          for(int j=0;j<W_SIZE;j++){
            a=Y[i][(j-1+W_SIZE)%W_SIZE]; b=Y[i][j]; c=Y[i][(j+1)%W_SIZE];
            X[i][j]=statestwo[c+3*b+9*a];//awesome base three arithmetic!
            if(X[i][j]>Y[i][j]) mobility++;
          }
        }
      }
      return;
    }
    
    void trafficset(){
      //for initializing the X. Always start with X, not Y!
      int n, xn, yn;
      for(int j=0;j<H_SIZE;j++){
        for(int k=0;k<W_SIZE;k++){
          X[j][k]=0;//initialize everything to zero!
        }
      }
      for(int i=0;i<PERCENT*H_SIZE*W_SIZE/200;i++){
        do{
          n=rand()%(H_SIZE*W_SIZE);
        }while(X[n/W_SIZE][n%W_SIZE]!=0);//find a random place that's empty
        X[n/W_SIZE][n%W_SIZE]=1;         //set that as a one
        do{
          n=rand()%(H_SIZE*W_SIZE);
        }while(X[n/W_SIZE][n%W_SIZE]!=0);//find a random place that's empty
        X[n/W_SIZE][n%W_SIZE]=2;         //set that as a two
      }
      return;
    }
    
    void setup(){
      size(W_SIZE*cellSize,(H_SIZE+20)*cellSize);
      trafficset();
      textFont(createFont("Arial",30,true));
      noStroke();
      frameRate(60);
    }
    
    void draw(){
      background(0);
      trafficroll(twoorone?one:two);
      for(int j=0;j<H_SIZE;j++){
        for(int k=0;k<W_SIZE;k++){
          if(twoorone){
            fill(Y[j][k]==0?#ffffff:(Y[j][k]==1?#ff0000:#0000ff));//two
          }else{
            fill(X[j][k]==0?#ffffff:(Y[j][k]==1?#ff0000:#0000ff));//one
          }
          rect(k*cellSize,j*cellSize,cellSize,cellSize);
        }
      }
      twoorone=!twoorone;
      fill(#ff0000);
      triangle(cellSize*PERCENT*W_SIZE/100,cellSize*(H_SIZE+10),
        cellSize*(PERCENT*W_SIZE/100-5),cellSize*(H_SIZE+18),
        cellSize*(PERCENT*W_SIZE/100+5),cellSize*(H_SIZE+18));
      text(PERCENT,cellSize*(W_SIZE-40),cellSize*(H_SIZE+18));
    }
    
    void mouseDragged(){
      if(mouseY>H_SIZE*cellSize){
        PERCENT=mouseX*100/(W_SIZE*cellSize);
        trafficset();
      }
    }
    
    //Biham-Middleton-Levine Traffic Model in Processing
    //Daniel L. Lu
    
    int xsize = 769, ysize = 256, speed = 3, fpsTheoretical = 60, 
      speedCursor = 160, densityCursor = 346, iterations = 0, mobility = 0, population;
    
    float density = 35;
    
    int []rule = {0,0,0,0,2,2,1,1,1,2,2,2,0,2,2,1,1,1,0,0,0,0,2,2,1,1,1};
    int []pixles = new int [xsize*ysize];
    int []slexip = new int [xsize*ysize];
    
    int x, y;
    
    int color2state(color c){
      return c==#FF0000?1:(c==#0000FF?2:0);
    }
    
    color state2color(int s){
      return s==1?#FF0000:(s==2?#0000FF:#FFFFFF);
    }
    
    void trafficSet(){
      background(#FFFFFF);
      hud();
      loadPixels();
      population = 0;
      for(x=0; x<xsize; x++){
        for(y=0; y<ysize; y++){
          if(random(100)<density){
            if(random(100)<50){
              pixels[y*xsize+x] = #FF0000;
              population++;
            }else{
              pixels[y*xsize+x] = #0000FF;
              population++;
            }
          }
        }
      }
      iterations = 0;
      mobility = 0;
      for(int i = 0; i<xsize*ysize; i++){
        pixles[i] = color2state(pixels[i]);
      }
      updatePixels();
    }
    
    void hud(){
      fill(#FFFFFF);
      rect(0,ysize,xsize,40);
      fill(#000000);
      text("speed: " + (int)(frameRate*speed),20, ysize+20);
      text("density: " + density/100, 276, ysize+20);
      text("iter: " + iterations, 532, ysize+20);
      if(population!=0){
        text("mobility: " + 1000*mobility/population/10.0 + "%", 532, ysize+40);
      }
        
      fill(#888888);
      text("(" + fpsTheoretical+"*"+speed + ")", 110, ysize+20);
      rect(20, ysize+30, 200, 4);
      rect(276, ysize+30, 200, 4);
      //rect(532, ysize+30, 200, 4);
      fill(#444444);
      ellipse(speedCursor, ysize+32, 8, 8);
      ellipse(densityCursor, ysize+32, 8, 8);
    }
      
    
    void setup(){
      frameRate(fpsTheoretical);
      textSize(14);
      ellipseMode(CENTER);
      noStroke();
      size(769,306);
      trafficSet();
    }
    
    void draw(){
      for(int i=0; i<speed; i++){
        iterations++;
        if(iterations%(fpsTheoretical*speed/3)!=0){//mobility calculations are expensive, so we only do it 3 times per second.
          for(x = 0; x<xsize; x++){
            for(y = 0; y<ysize; y++){
              slexip[y*xsize+x] = rule[pixles[y*xsize+(x+1)%xsize]+3*pixles[y*xsize+x]+9*pixles[y*xsize+(x+xsize-1)%xsize]];
            }
          }
          for(x = 0; x<xsize; x++){
            for(y = 0; y<ysize; y++){
              pixles[y*xsize+x] = rule[slexip[x+((y+1)%ysize)*xsize]+3*slexip[y*xsize+x]+9*slexip[x+((y+ysize-1)%ysize)*xsize]];
            }
          }
        }else{
          mobility = 0;
          for(x = 0; x<xsize; x++){
            for(y = 0; y<ysize; y++){
              slexip[y*xsize+x] = rule[pixles[y*xsize+(x+1)%xsize]+3*pixles[y*xsize+x]+9*pixles[y*xsize+(x+xsize-1)%xsize]];
              mobility+=(slexip[y*xsize+x]!=0 && pixles[y*xsize+x]==0)?1:0;
            }
          }
          for(x = 0; x<xsize; x++){
            for(y = 0; y<ysize; y++){
              pixles[y*xsize+x] = rule[slexip[x+((y+1)%ysize)*xsize]+3*slexip[y*xsize+x]+9*slexip[x+((y+ysize-1)%ysize)*xsize]];
              mobility+=(pixles[y*xsize+x]!=0 && slexip[y*xsize+x]==0)?1:0;
            }
          }
        }      
      }
      for(int i = 0; i<xsize*ysize; i++){
        pixels[i] = state2color(pixles[i]);
      }
      updatePixels();
      hud();
    }
    
    void mouseDragged(){
      if(mouseY>ysize+10){
        if(mouseX>=276 && mouseX<=476){
          density = 100.0*(mouseX-276)/200;
          trafficSet();
          densityCursor = mouseX;
        }else if(mouseX>=20 && mouseX<=30){
          speed = 0;
          fpsTheoretical = 60;
          speedCursor = mouseX;
          frameRate(fpsTheoretical);
        }else if(mouseX>30 && mouseX<=140){
          fpsTheoretical = (mouseX-20)/2;
          speed = 1;
          speedCursor = mouseX;
          frameRate(fpsTheoretical);
        }else if(mouseX>140 && mouseX<=220){
          speed = (mouseX-140+10)/10;
          fpsTheoretical = 60;
          speedCursor = mouseX;
          frameRate(fpsTheoretical);
        }
      }
    }
    

    code

    tweaks (0)

    license

    advertisement

    Daniel Lu

    Biham-Middleton-Levine Traffic Model

    Add to Faves Me Likey@! 7
    You must login/register to add this sketch to your favorites.

    The Biham-Middleton-Levine traffic model is a self-organizing cellular automaton traffic flow model. It consists of a number of cars represented by points on a lattice with a random starting position, where each car may be one of two types: those that only move downwards (red), and those that only move towards the right (blue). The two types of cars take turns to move. During each turn, all the cars for the corresponding type move by one step if possible. The slider at the bottom controls the traffic density in percent. Changing this resets the entire system.

    You need to login/register to comment.