ラングトンの蟻 [Processing]
Processingでラングトンの蟻のシミュレーションを行った.
ラングトンの蟻とは
ラングトンのアリ - Wikipediaより引用.
平面が格子状に構成され、各マスが白または黒で塗られる。ここで、1つのマスを「アリ」とする。アリは各ステップで上下左右のいずれかのマスに移動することができる。アリは以下の規則に従って移動する。
この単純な規則で驚くほど複雑な動作をする。当初でたらめな動作をしているが、アリはいずれ例外なく10000歩ほどうろついた後に真っ直ぐな「道」を作る動作に入る。これは初期のパターンがどうであろうと殆ど関係ない。このことは、この「道」(highway)が、ラングトンのアリのアトラクタであることを示唆している。
ソースコード
int CELL_NUM = 100; int CELL_SIZE = 5; boolean[][] cells = new boolean[CELL_NUM][CELL_NUM]; int ant_x; int ant_y; int ant_direction; // 0=up, 1=right, 2=bottom, 3=left void setup(){ size(CELL_NUM * CELL_SIZE, CELL_NUM * CELL_SIZE); // initialize cells, 0: all white, 1: all black, 2: put black rectangle initialize_cells(0); // initialize ant position ant_x = ant_y = int(CELL_NUM / 2); ant_direction = 0; } void draw(){ // clear screen fill(255); rect(0, 0, width, height); // draw cells noStroke(); fill(30); for(int w = 0; w < CELL_NUM; w++){ for(int h = 0; h < CELL_NUM; h++){ if(cells[w][h] == true){ rect(w * CELL_SIZE, h * CELL_SIZE, CELL_SIZE, CELL_SIZE); } } } // draw lines stroke(128); strokeWeight(1); for(int i = 0; i < CELL_NUM; i++){ line(i * CELL_SIZE, 0, i * CELL_SIZE, height); line(0, i * CELL_SIZE, width, i * CELL_SIZE); } // draw ant fill(255, 0, 0); rect(ant_x * CELL_SIZE, ant_y * CELL_SIZE, CELL_SIZE, CELL_SIZE); //act ant act_ant(); } void act_ant(){ if(cells[ant_x][ant_y] == true){ turn_left(); } else { turn_right(); } cells[ant_x][ant_y] = !cells[ant_x][ant_y]; forward_ant(); } void turn_left(){ ant_direction -= 1; if(ant_direction == -1){ ant_direction = 3; } } void turn_right(){ ant_direction += 1; if(ant_direction == 4){ ant_direction = 0; } } void forward_ant(){ switch(ant_direction){ case 0: ant_y = (ant_y != 0 ? ant_y - 1 : CELL_NUM - 1); break; case 1: ant_x = (ant_x != CELL_NUM - 1 ? ant_x + 1 : 0); break; case 2: ant_y = (ant_y != CELL_NUM - 1 ? ant_y + 1 : 0); break; case 3: ant_x = (ant_x != 0 ? ant_x - 1 : CELL_NUM - 1); break; } } void initialize_cells(int method){ switch(method){ case 0: // all white for(int w = 0; w < CELL_NUM; w++){ for(int h = 0; h < CELL_NUM; h++){ cells[w][h] = false; } } break; case 1: // all black for(int w = 0; w < CELL_NUM; w++){ for(int h = 0; h < CELL_NUM; h++){ cells[w][h] = true; } } break; case 2: // put black rectangle for(int w = 0; w < CELL_NUM; w++){ for(int h = 0; h < CELL_NUM; h++){ cells[w][h] = false; } } int rect_x = 40; int rect_y = 20; for(int w = (CELL_NUM / 2) - int(rect_x / 2); w < (CELL_NUM / 2) + int(rect_x / 2); w++){ for(int h = (CELL_NUM / 2) - int(rect_y / 2); h < (CELL_NUM / 2) + int(rect_y / 2); h++){ cells[w][h] = true; } } } }
シミュレーション
動画1
真っ白の空間からスタートさせたもの.
ランダムな動きをするが,およそ10000ステップ後に道作りに入っている.
動画2
真ん中に黒い直方体を置いてスタートさせたもの.
黒い長方形を壊したり,壁を作ったりしながら,こちらも10000ステップ後に道作りに入っている,
processing.jsを用いて,Webブラウザからも見れるようにしておいた.