セルオートマトン
提供:kuhalaboWiki
(版間での差分)
(→セルオートマトン資料) |
(→セルオートマトン) |
||
| 1行: | 1行: | ||
| − | |||
[https://ja.wikipedia.org/wiki/%E3%82%BB%E3%83%AB%E3%83%BB%E3%82%AA%E3%83%BC%E3%83%88%E3%83%9E%E3%83%88%E3%83%B3 Wikipedia] | [https://ja.wikipedia.org/wiki/%E3%82%BB%E3%83%AB%E3%83%BB%E3%82%AA%E3%83%BC%E3%83%88%E3%83%9E%E3%83%88%E3%83%B3 Wikipedia] | ||
| − | + | == パスカルの三角形 == | |
http://www.xn--u9jtgqbzf1fn77phnzag74e.jp/pascul-nature.html | http://www.xn--u9jtgqbzf1fn77phnzag74e.jp/pascul-nature.html | ||
| 121行: | 120行: | ||
** 11 -> 0 or 1 | ** 11 -> 0 or 1 | ||
| − | + | == 基本セルオートマトン == | |
*隣接する3つのセルで次の状態が決まる。 | *隣接する3つのセルで次の状態が決まる。 | ||
*セルの状態は、0,1 | *セルの状態は、0,1 | ||
| 286行: | 285行: | ||
</pre> | </pre> | ||
| − | + | == 2次元セルオートマトン == | |
;正方格子 | ;正方格子 | ||
| 361行: | 360行: | ||
</pre> | </pre> | ||
| − | + | == ライフゲーム == | |
*[https://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B2%E3%83%BC%E3%83%A0 ライフゲーム] | *[https://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B2%E3%83%BC%E3%83%A0 ライフゲーム] | ||
*[https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life Conway's Game of Life] | *[https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life Conway's Game of Life] | ||
| 450行: | 449行: | ||
</pre> | </pre> | ||
| − | + | == 正六角形セルオートマトン == | |
;六角格子 | ;六角格子 | ||
ベクトルPVectorクラスを使った図形描画PShapeで六角格子を作る。 | ベクトルPVectorクラスを使った図形描画PShapeで六角格子を作る。 | ||
| 562行: | 561行: | ||
</pre> | </pre> | ||
| − | + | == セルオートマトン資料 == | |
*[http://www.kuhalabo.net/~kuha/tutorial0/bioart/Lifegame.exe ライフゲームのWindowsソフト] / | *[http://www.kuhalabo.net/~kuha/tutorial0/bioart/Lifegame.exe ライフゲームのWindowsソフト] / | ||
2020年10月30日 (金) 00:54時点における版
目次 |
パスカルの三角形
http://www.xn--u9jtgqbzf1fn77phnzag74e.jp/pascul-nature.html
- 数字を書くプログラム
- textSize() 文字の大きさを決める。
- text(txt,x ,y) txtという文字列を(x,y)に書く。
- splice(配列a,値v, 場所i) 配列aに値vを場所i(先頭からi番目)に挿入します。
int num = 8; //計算する世代数の上限
int[] state = {1}; //初期状態
int gen = 0; //世代
void setup(){
size(500, 500);
}
void draw(){
if(gen < num){
drawNumber(gen); //数字を書く
updateState(); //状態を更新する
}
}
void drawNumber(float y){
float scalar = (float) width / num; // 数字の大きさ
float x = (width - state.length * scalar) * 0.5; // 数字を書く位置のx座標
y *= scalar;
fill(0);
for (int i = 0; i < state.length; i++){
textSize(scalar * 0.5);
text(state[i], x + scalar * 0.5, y + scalar * 0.5);
x += scalar; // 数字を書く位置をx座標方向にずらす
}
}
void updateState(){
int[] BOUNDARY = {0}; //境界値(文字がない所)を0とする
int[] nextState = new int[state.length + 1]; // 次の世代の状態
state = splice(state, BOUNDARY, 0); // 配列の最初に境界値を加える
state = splice(state, BOUNDARY, state.length); // 配列の最後に境界値を加える
for (int i = 0; i < state.length - 1; i++){
nextState[i] = transition(i); // 次世代の状態の計算
}
state = nextState; // 状態を更新
gen++; //世代を1つ増やす
}
int transition(int i){
int nextC = state[i + 1] + state[i]; //パスカルの法則に従った計算
return nextC;
}
- 数値をmodで標記
- mod 割り算のあまり。
- 0,1のパスカルの三角形の遷移ルール
- (0+0) % 2 -> 0
- (0+1) % 2 -> 1
- (1+0) % 2 -> 1
- (1+1) % 2 -> 0
int num = 250;
int mod = 2;
int[] state = {1};
int gen = 0;
void setup(){
size(500, 500);
colorMode(HSB, 1);
background(0, 0, 1);
}
void draw(){
if (gen < num){
drawCell(gen);
updateState();
}
}
void drawCell(float y){
float scalar = (float) width / num; // セルの大きさ
float x = (width - state.length * scalar) * 0.5; // セルのx座標
y *= scalar;
noStroke();
for (int i = 0; i < state.length; i++){
fill(state[i] * 1.0 / mod, state[i] * 1.0 / mod, 1); //色相にセルの状態を割り当て
rect(x, y, scalar, scalar); // セルの描画
x += scalar; // x座標方向にセルをずらす
}
}
void updateState(){
int[] BOUNDARY = {0};
int[] nextState = new int[state.length + 1]; // 次の行の配列
state = splice(state, BOUNDARY, 0); // 配列stateの最初に{0,0}を加える
state = splice(state, BOUNDARY, state.length); // 配列stateの最後に{0,0}を加える
for (int i = 0; i < state.length - 1; i++){
nextState[i] = transition(i); // 次世代のセルの状態の計算
}
state = nextState; // セルの状態を更新
gen++;
}
int transition(int i){
int nextC = (state[i + 1] + state[i]) % mod; // 遷移規則
return nextC;
}
- セルピンスキーのギャスケット
- 0,1のパスカルの三角形の遷移ルール
- 隣接する2つのセルで次の状態が決まる。
- 00 -> 0 or 1
- 01 -> 0 or 1
- 10 -> 0 or 1
- 11 -> 0 or 1
基本セルオートマトン
- 隣接する3つのセルで次の状態が決まる。
- セルの状態は、0,1
- 000 -> 0 or 1
- 001 -> 0 or 1
- 010 -> 0 or 1
- 011 -> 0 or 1
- 100 -> 0 or 1
- 101 -> 0 or 1
- 110 -> 0 or 1
- 111 -> 0 or 1
- 0 or 1 が8通りあるので、合計 2の8乗=256通りのルールがある。
- Wolframは256通りのルールをすべて調べた。
- Elementary Cellular Automaton, Wolfram Math World
- 全て0の00000000(ルール0)から全て1の11111111(ルール255)まで
基本セルオートマトンのソース例
- c(t+1,i) = c(t,i-1) + c(t,i) + c(t,i+1) の例
- 0+0=0, 0+1=0+1=1, 1+1=0 (2進数では10だが、1桁目のみ残す)
- 000 -> 0
- 001 -> 1
- 010 -> 1
- 011 -> 0
- 100 -> 1
- 101 -> 0
- 110 -> 0
- 111 -> 1
int num = 250; //表示する世代数
int mod = 2; //法とする数
int[] state = {1}; //初期状態
int gen = 0;
void setup(){
size(1000, 500);
colorMode(HSB, 1);
background(0, 0, 1);
}
void draw(){
if (gen < num){
drawCell(gen);
updateState();
}
}
void mouseClicked(){
gen = 0;
state = new int[]{1}; //初期状態
mod = int(random(2, 20));
println(mod);
background(0, 0, 1);
}
void drawCell(float y){
float scalar = width * 0.5 / num; // セルの大きさ
float x = (width - state.length * scalar) * 0.5; // セルのx座標
y *= scalar;
noStroke();
for (int i = 0; i < state.length; i++){
fill(state[i] * 1.0 / mod, state[i] * 1.0 / mod, 1); //色相にセルの状態を割り当て
rect(x, y, scalar, scalar); // セルの描画
x += scalar; // x座標方向にセルをずらす
}
}
void updateState(){
int[] BOUNDARY = {0, 0};
int[] nextState = new int[state.length + 2]; // 次の世代の状態
state = splice(state, BOUNDARY, 0); // 配列の最初に境界値を加える
state = splice(state, BOUNDARY, state.length); // 配列の最後に境界値を加える
for (int i = 1; i < state.length - 1; i++){
nextState[i-1] = transition(state[i - 1], state[i], state[i + 1]); // 次世代のセルの状態の計算
}
state = nextState; // セルの状態を更新
gen++; //世代を1つ増やす
}
int transition(int a, int b, int c){
int d = a + b + c; //遷移ルールに従って計算
d = d % mod;
return d;
}
- 遷移ルールに確率的要素を入れる
int transition(int a, int b, int c){
int d;
if (random(1) < 0.999){
d = a + b + c; //99.9%の確率でこのルールを選択
} else {
d = a + c; //0.1%の確率でこのルールを選択
}
d = d % mod;
return d;
}
- マウスクリックするたびに、遷移ルールを変えて描画
int num = 250; //表示する世代数
int mod = 2; //法とする数
int[] state = {1}; //初期状態
int[] rule = {0, 0, 0, 1, 1, 1, 1, 0}; // rule 30 (0011110)
float gen = 0;
void setup(){
size(1000, 500);
colorMode(HSB, 1);
}
void draw(){
if (gen < num){
drawCell(gen);
updateState();
}
}
void mouseClicked(){
gen = 0;
state = new int[]{1}; //初期状態
rule = new int[8];
int ruleInt = 0;
for (int i = 0; i < 8; i++){
rule[i] = int(random(2));
ruleInt += rule[i] * int(pow(2, 7 - i));
}
println(ruleInt);
background(0, 0, 1);
}
void drawCell(float y){
float scalar = width * 0.5 / num; // セルの大きさ
float x = (width - state.length * scalar) * 0.5; // セルのx座標
y *= scalar;
noStroke();
for (int i = 0; i < state.length; i++){
fill(0, 0, 1 - state[i]); //色相にセルの状態を割り当て
rect(x, y, scalar, scalar); // セルの描画
x += scalar; // x座標方向にセルをずらす
}
}
//8個の01要素からなる配列ruleに対して,遷移ルールを決定する
int transition(int a, int b, int c){
int d;
//abcを10進数に置き換える
int ruleInt = int(a * pow(2, 2) + b * pow(2, 1) + c * pow(2, 0));
d = rule[7 - ruleInt];
return d;
}
void updateState(){
int[] BOUNDARY = {0, 0};
int[] nextState = new int[state.length + 2]; // 次の行の配列
state = splice(state, BOUNDARY, 0); // 配列stateの最初に{0,0}を加える
state = splice(state, BOUNDARY, state.length); // 配列stateの最後に{0,0}を加える
for (int i = 1; i < state.length - 1; i++){
nextState[i-1] = transition(state[i - 1], state[i], state[i + 1]); // 次世代のセルの状態の計算
}
state = nextState; // セルの状態を更新
gen++;
}
2次元セルオートマトン
- 正方格子
- 遷移ルールの例
- a
- b c d
- e
next c = a+b+c+d+e mod n
int num = 250; // 行と列の長さ
int mod = 4; // 法とする数
int[][] state = new int[num][num]; // セルの状態を表す行列
void setup(){
size(500, 500);
colorMode(HSB, 1);
initialize(); // 初期化する
frameRate(2); // 0.5秒ごとに遷移
}
void draw(){
drawCell();
updateState();
}
void initialize(){
for (int i = 0; i < num; i++){
for (int j = 0; j < num; j++){
if (i == num / 2 && j == num / 2){
state[i][j] = 1; // 真ん中の成分のみ1
} else {
state[i][j] = 0;
}
}
}
}
void updateState(){
int[][] nextState = new int[num][num]; // 次世代の状態
for (int i = 0; i < num; i++){
for (int j = 0; j < num; j++){
nextState[i][j] = transition(i, j); // 遷移
}
}
state = nextState; //更新
}
int transition(int i, int j){
int nextC;
nextC = state[(i - 1 + num) % num][j] //上のセル
+ state[i][(j - 1 + num) % num] //左のセル
+ state[i][j] //中央のセル
+ state[i][(j + 1) % num] //右のセル
+ state[(i + 1) % num][j]; //下のセル
nextC = nextC % mod;
return nextC;
}
void drawCell(){
float scalar = (float) height / num; // セルのサイズ
float y = 0; // セルのy座標
float x;
for (int i = 0; i < num; i++){
x = 0; // セルのx座標
for (int j = 0; j < num; j++){
noStroke();
fill(state[i][j] * 1.0 / mod, state[i][j] * 1.0 / mod, 1); // セルの色
rect(x, y, scalar, scalar);
x += scalar;
}
y += scalar;
}
}
ライフゲーム
- 遷移ルール
- セルの状態は、生(1)か死(0)か
- セルが1の場合
- 自分の周りに1が2個か3個の場合、1
- それ以外の場合、0
- セルが0の場合
- 自分の周りに1が3個の場合、1
- それ以外の場合、0
- 初期化
- ランダムに生と死を配置
- num = 50;
- mod = 1;
- frameRate(4);
void initialize(){
float r;
for (int i = 0; i < num; i++){
for (int j = 0; j < num; j++){
r = random(100);
if ( r > 85 ){
state[i][j] = 1;
} else {
state[i][j] = 0;
}
}
}
}
- 遷移ルール
int transition(int i, int j){
int aroundC;
int nextC = 0;
aroundC =
state[(i - 1 + num) % num][j] //上のセル
+ state[(i - 1 + num) % num][(j - 1 + num) % num] //上のセル
+ state[(i - 1 + num) % num][(j + 1) % num] //上のセル
+ state[i][(j - 1 + num) % num] //左のセル
+ state[i][(j + 1) % num] //右のセル
+ state[(i + 1) % num][(j - 1 + num) % num] //下のセル
+ state[(i + 1) % num][j] //下のセル
+ state[(i + 1) % num][(j + 1) % num]; //下のセル
if(state[i][j] == 1){
if(aroundC == 2 || aroundC == 3) {
nextC = 1;
}
else{
nextC = 0;
}
}
if(state[i][j] == 0){
if(aroundC == 3) {
nextC = 1;
}
else{
nextC = 0;
}
}
return nextC;
}
void drawCell(){
float scalar = (float) height / num; // セルのサイズ
float y = 0; // セルのy座標
float x;
for (int i = 0; i < num; i++){
x = 0; // セルのx座標
for (int j = 0; j < num; j++){
noStroke();
fill(state[i][j] * 1.0, state[i][j] * 1.0, 1); // セルの色
rect(x, y, scalar, scalar);
x += scalar;
}
y += scalar;
}
}
正六角形セルオートマトン
- 六角格子
ベクトルPVectorクラスを使った図形描画PShapeで六角格子を作る。
- beginShape()とendShape()の間にvertex()で頂点を並べて、図形を描く。vertexについて解説
- createShape()で図形を作成して、再利用する。
PVector[][] lattice;
PShape tile;
PVector[] base = new PVector[2]; //格子を張るベクトル
int num = 100; //描画する格子の行数
float scalar;
int[][] state = new int[num][num]; //セルの状態を表す行列
int mod = 10; //法とする数
void setup(){
size(600, 800);
colorMode(HSB, 1);
scalar = height * 1.0 / num; //ウィンドウと格子の行数から格子の大きさを決定
initialize(); // 初期状態
makeHexVector(); //六角格子を張るベクトルの生成
makeLattice(); //格子点ベクトルを生成
makeHex(); //正六角形タイルを生成
drawTiling(); //タイリングを描画
frameRate(2);
}
void draw(){
background(0, 0, 1);
int[][] nextState = new int[num][num]; //次世代の行列
for (int i = 0; i < num; i++){
for (int j = 0; j < num; j++){
nextState[i][j] = transition(i, j); //遷移
}
}
state = nextState; //状態を更新
drawTiling();
}
void initialize(){
for (int i = 0; i < num; i++){
for (int j = 0; j < num; j++){
if (i == num / 2 && j == num / 2){
state[i][j] = 1; // 中央の成分のみ1
} else {
state[i][j] = 0;
}
}
}
}
//六角格子を張るベクトルを作る。
//円周上の時計回りに90度(PI/2)と30度(PI/6)に点を取ってベクトルを作る。
void makeHexVector(){
base[0] = PVector.fromAngle(PI/2);
base[1] = PVector.fromAngle(PI/6);
}
//ウィンドウ内に収まるように格子点の配列latticeを定める。
//ウィンドウからはみ出た格子点は%(余り)演算でウィンドウ上部に戻す。
void makeLattice(){
lattice = new PVector[num][num];
for (int i = 0; i < num; i++){
for (int j = 0; j < num; j++){
PVector v = PVector.mult(base[0], i * scalar);
v.add(PVector.mult(base[1], j * scalar));
lattice[i][j] = new PVector(v.x, v.y % height);
}
}
}
//fromAngleで60度(PI/3)刻みで正6角形の格子を作る
//
void makeHex(){
tile = createShape();
tile.beginShape();
tile.noStroke();
for (int i = 0; i < 6; i++){
PVector v = PVector.fromAngle(2 * PI * i / 6);
v.mult(scalar / sqrt(3));
tile.vertex(v.x, v.y);
}
tile.endShape(CLOSE);
}
//makeHex関数で作った正6角形の格子に沿って配置する。
void drawTiling(){
for (int i = 0; i < num; i++){
for (int j = 0; j < num; j++){
tile.resetMatrix();
tile.translate(lattice[i][j].x, lattice[i][j].y); //タイルの位置を指定
setTileColor(tile, i, j);
shape(tile); //タイルを描画
}
}
}
void setTileColor(PShape t, int i, int j){
t.setFill(color(state[i][j] * 1.0 / mod, state[i][j] * 1.0 / mod, 1));
}
int transition(int i, int j){
int d;
d = state[i][j] //中央のセル
+ state[(i - 1 + num) % num][j] //上のセル
+ state[(i - 1 + num) % num][(j + 1) % num] //右上のセル
+ state[i][(j + 1) % num] //右下のセル
+ state[(i + 1) % num][j] //下のセル
+ state[(i + 1) % num][(j - 1 + num) % num] //左下のセル
+ state[i][(j - 1 + num) % num]; //左上のセル
d = d % mod;
return d;
}
セルオートマトン資料
- ライフゲームのWindowsソフト /
- Cellular Automata explorer
- Wolfram Math World Game of Life
- HashLife
- http://golly.sourceforge.net/
- セルオートマトン音楽
- WolframTones
- Life Game Orchestra : Doccument / YouTube
ワイヤワールド /