ライフゲーム(fortran)
Fortranの勉強し始めたとき,遊んだライフゲームを書いてみます.
まずは,
ライフゲームとは
1970年にケンブリッジ大のコンウェイが発明したセルオートマトン.初期条件を与えれば一定の規則で世代が進み,生と死を表すセルが更新されていきます(参照 ライフゲーム - Wikipedia)1.1974年にはTime誌が「ライフゲイムの大群が数百万ドルの貴重なコンピュータ時間を食ってしまっている」と苦言を呈したほど流行ったらしいです2.
代表的なパターン
有名なパターンをいくつか紹介します.白いセルが「生(1)」を,黒いセルが「死(0)」を表しています.個人的にはたった5つの「生」でスタートし,煩雑な模様を展開するR pentominoが面白いです.
例1:Nebula
例2:R pentomino
例3:Glider(周期境界条件)
例4:Puffer train
ソースコード
プログラムはQiita記事を参考にさせて頂きました3.
描画領域を正方形にして,初期条件を乱数ではなく,Excelで作成した init_field.txt から読み込ませています.
また,境界の条件はcshift
とeoshift
を使い分けて,固定境界か周期境界かを選べます.Gliderとかは周期境界にしました.
Fortran90/95
! Conway's Game of Life module lifegame implicit none integer :: n integer, allocatable :: field( : , : ) integer, allocatable :: neighbors( : , : ) contains subroutine init_field( size ) integer, intent( in ) :: size integer i integer ios n = size allocate( field( n, n ) ) allocate( neighbors( n, n ) ) open(10, file="init_field.txt") do i=0, n read(10, *, iostat=ios) field if (ios .lt. 0) exit end do close(10) end subroutine init_field subroutine print_field() implicit none integer :: i do i = 1, n write (*, '( * ( i0, :, " " ) )' ) field( :, i ) end do end subroutine print_field subroutine one_epoch implicit none integer :: dx, dy, i neighbors = 0 do concurrent ( dx = -1 : 1, dy = -1 : 1 ) ! 周期境界条件(cshift) neighbors = neighbors + cshift( cshift(field, dx, 1), dy, 2 ) ! 固定境界条件(eoshift, 境界の外は死(0)) ! neighbors = neighbors + eoshift( eoshift(field, dx, 0, 1), dy, 0, 2 ) end do where( neighbors == 3 ) field = 1 elsewhere( neighbors == 4 ) field = field elsewhere field = 0 endwhere end subroutine one_epoch end module lifegame ! MainProgram program main use lifegame implicit none integer :: epoch, size integer :: i write( *, * ) "# size?" read( *, * ) size write( *, * ) "# epoch?" read( *, * ) epoch call init_field( size ) call print_field do i = 1, epoch call one_epoch write (*, *) call print_field end do stop end program main
Excelファイルはこんな感じで作成して,テキストファイル(init_field.txt)に出力しました.
以下はGliderの例.
以下,gnuplotでgifアニメを作成します.
gnuplot
reset set term gif animate size 560, 400 # 出力をgifアニメに設定 set output "field.gif" # 出力ファイル名 set size square set nozeroaxis set notics unset colorbox set palette grey # gray0 = 黒 set title font "Arial,30" set key below do for [n=0:1000:1] { plot "field.log" index n matrix with image title sprintf("generation %d", n) }
おわりに
昨年から上記のライフゲームのプログラムとか
でやんわりとFortranの勉強始めました.