Fortran - セル・オートマトン!
Updated:
Fortran 95 でセル・オートマトンの実装を試してみました。
0. 前提条件
- LMDE 3 (Linux Mint Debian Edition 3; 64bit) での作業を想定。
- GCC 6.3.0 (GFortran 6.3.0) でのコンパイルを想定。
1. セル・オートマトンとは
格子状のセル上で、周囲のセルとのやりとりを単純なルールで定め、そのルールに則って、次の世代(ステップ)を決めていくような離散的計算モデルのことである。(Cellular Automaton; CA)
ライフゲームもセル・オートマトンの一種。
2. ソースコードの作成
File: cell_atm.f95
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
!****************************************************
! セル・オートマトン
!
! date name version
! 2018.09.14 mk-mode.com 1.00 新規作成
!
! Copyright(C) 2018 mk-mode.com All Rights Reserved.
!****************************************************
!
program CellAtm
implicit none
integer, parameter:: rule = 90 ! 遷移規則 (90, 30, 110, 184)
real(8), parameter:: density = 0.04 ! 初期状態密度
integer, parameter:: W = 78, H = 20 ! 横幅,縦長さ
integer(1) :: a(1:W), s(1:W) ! セル状態 a, 近傍状態 s
integer :: i
call random_array(a, W, density) ! 初期状態を a にセット
print *, merge('X', ' ', a/=0) ! 表示 1 -> X
do i = 1, H ! H 回遷移を繰り返し
s(1) = a(W) * 4 + a(1) * 2 + a(2) ! 左端の近傍状態
s(W) = a(W-1) * 4 + a(W) * 2 + a(1) ! 右端の近傍状態
s(2:W-1) = a(1:W-2) * 4 + a(2:W-1) * 2 + a(3:W) ! 他の近傍状態
a = merge(1, 0, btest(rule, s)) ! 遷移実行
print *, merge('X', ' ', a/=0) ! 表示 1 -> X
end do
stop
contains
subroutine random_array(a, n, densty )
integer :: n
integer(1) :: a(1:n)
real(8) :: densty
integer :: ck, sz, i
real(8) :: rnd(1:n)
call system_clock(ck) ! クロック値 ( 毎回違う ) を取得
call random_seed(size=sz) ! 乱数シードの数を取得
call random_seed(put=(/(ck+i, i=1,sz)/)) ! 乱数初期値変更
call random_number(rnd) ! rnd に n 個の乱数をセット
a = merge(1, 0, rnd < densty) ! a に密度 densty の 1 をセット
end subroutine random_array
end program CellAtm
3. ソースコードのコンパイル
$ gfortran -o cell_atm cell_atm.f95
4. 動作確認
$ ./cell_atm
X
X X
X X
X X X X
X X
X X X X
X X X X
X X X X X X X X
X X
X X X X
X X X X
X X X X X X X X
X X X X
X X X X X X X X
X X X X X X X X
X X X X X X X X X X X X X X X X
X X
X X X X
X X X X
X X X X X X X X
X X X X
5. ソースコード(C 言語連携バージョン)の作成
C 言語と連携して PGM 画像を生成するようにしたバージョン。
File: cell_atmt.f95
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
!****************************************************
! セル・オートマトン(C 言語との連携バージョン)
!
! date name version
! 2018.09.14 mk-mode.com 1.00 新規作成
!
! Copyright(C) 2018 mk-mode.com All Rights Reserved.
!****************************************************
!
program CellAtm
implicit none
integer, parameter:: rule = 110 ! 遷移規則 (90, 30, 110, 184)
real(8), parameter:: density = 0.01 ! 初期状態密度
integer, parameter:: W = 800, H = 750 ! 横幅,縦長さ
integer(1) :: a(1:W), s(1:W) ! セル状態 a, 近傍状態 s
integer :: i
call random_array(a, W, density) ! 初期状態を a にセット
call put_head(W, H + 1, 1) ! 出力初期化ルーチン (C)
call put_raw(a, W) ! 出力ルーチン (C)
do i = 1, H ! H 回遷移を繰り返し
s = cshift(a,-1)*4 + a*2 + cshift(a,1) ! 近傍状態計算
a = merge(1, 0, btest(rule, s)) ! 遷移実行
call put_raw(a, W) ! 出力ルーチン (C)
end do
stop
contains
subroutine random_array(a, n, densty )
integer :: n
integer(1) :: a(1:n)
real(8) :: densty
integer :: ck, sz, i
real(8) :: rnd(1:n)
call system_clock(ck) ! クロック値 ( 毎回違う ) を取得
call random_seed(size=sz) ! 乱数シードの数を取得
call random_seed(put=(/(ck+i, i=1,sz)/)) ! 乱数初期値変更
call random_number(rnd) ! rnd に n 個の乱数をセット
a = merge(1, 0, rnd < densty) ! a に密度 densty の 1 をセット
end subroutine random_array
end program CellAtm
File: pgmout.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
* PGM 出力用
*/
#include <stdio.h>
int Width, Height, Max;
void put_head_(int *width, int *height, int *max){
printf("P5\n%d %d\n%d\n", *width, *height, *max);
}
void put_raw_(char *a, int *width){
fwrite(a, 1, *width, stdout);
}
6. ソースコード(C 言語連携バージョン)のビルド
今回は Makefile を作成してビルド(コンパイル+リンク+実行可能ファイル作成)する。(以下は、当方の記述例)
まず、 Makefile の作成。
File: Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FC = gfortran
CFLAGS = -c -O
TARGET = cell_atmt
.SUFFIXES:.f95 .o
.f95.o:
$(FC) $(CFLAGS) $<
all: $(TARGET)
OBJS = pgmout.o cell_atmt.o
$(TARGET): $(OBJS)
$(FC) -o $@ $(OBJS)
clean:
@rm -f $(TARGET) $(OBJS)
- Makefile 内の行頭にあるインデントは「タブ」であること。
そして、ビルド。
$ make
7. 動作確認(C 言語連携バージョン)
$ ./cell_atmt | tee cell_atmt.pgm | display
PGM 画像 cell_atmt.pgm
が作成&表示される。
以上、
Comments