--/--/--

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
2011/06/28

セルオートマトンのプログラム ソース

カオスでCG2(入門)で取り扱った、セルオートマトンのプログラムのソースコードを載せます。

載せたプログラムは『ca1.c』『coord.c』の2つです。前者は、セルオートマトンのプログラム、後者は前者で出力された1と0の羅列をグラフに描くために座標上の点に変換するプログラムです。

プログラムの実行手順、gnuplotを用いて図形を描く手順はソースコードの後に示します。
クリックでその部分まで移動

/******************************************************/
/* ca1.cプログラム   */
/******************************************************/

/* セルオートマトン(1次元)計算プログラム */
/* ルールと初期状態から、時間発展を計算します */
/* 使い方 $./ca1 (ルール番号) <(初期状態ファイル名)*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define N 250 /*セルの最大個数*/
#define R 8 /*ルール表の大きさ*/
#define MAXT 200 /*繰り返しの回数*/
#define BUFSIZE 256 /*入力バッファ用配列の長さ*/

/*関数のプロトタイプ宣言*/
void setrule(char *arg,int rule[]) ;/*ルール表の初期化*/
void initca(int ca[]) ; /*初期値の読み込み*/
int cvalue(char ch) ;/*1文字の0/1への変換*/
void putca(int ca[]) ;/*caの状態の出力*/
void nextt(int ca[],int rule[]) ;/*次の時刻に更新*/

/**********************/
/* main関数 */
/**********************/
int main(int argc,char *argv[])
{
int t ;/*時刻を表す、反復回数のカウンタ*/
int ca[N]={0} ;/*セルの並び*/
int rule[R] ;/*ルール表*/

/*ルール表の初期化*/
if(argc<2){/*ルールの指定がない*/
fprintf(stderr,
"使い方 $ ./ca1(ルール番号)<(初期状態ファイル名)\n") ;
exit(1) ;
}
setrule(argv[1],rule) ;/*ルール表をセット*/

/*ca[]への初期値の読み込み*/
initca(ca) ;
putca(ca) ;/*ca[]の状態の出力*/

/*時間発展の計算*/
for(t=0;t<MAXT;++t){
nextt(ca,rule) ;/*次の時刻に更新*/
putca(ca) ;/*ca[]の状態の出力*/
}
return 0 ;
}

/***************************/
/* nextt()関数 */
/* caの状態の更新 */
/***************************/

void nextt(int ca[],int rule[])
{
int nextca[N]={0} ;/*次世代のca[]*/
int i;

/*ルールの適用*/
for(i=1;i<N-1;i++)
nextca[i]=rule[ca[i+1]*4+ca[i]*2+ca[i-1]] ;

/*caの更新*/
for(i=0;i<N;++i)
ca[i]=nextca[i] ;
}


/**************************/
/*   putca()関数    */
/* caの状態の出力 */
/**************************/
void putca(int ca[])
{
int i ;
for(i=N-1;i>=0;--i)
printf("%1d",ca[i]) ;
printf("\n") ;
}

/**************************/
/* initca()関数 */
/* 初期値の読み込み */
/**************************/
void initca(int ca[])
{
char linebuf[BUFSIZE] ;/*1行入力用の文字配列*/
int i=0 ;

/*初期値を読み込む*/
if(fgets(linebuf,BUFSIZE,stdin)==NULL){/*読み取り失敗*/
fprintf(stderr,"初期値の読み取りに失敗しました\n") ;
exit(1) ;
}

/*初期値の設定*/
for(i=0;linebuf[i]!='\0';++i)
ca[N-1-i]=cvalue(linebuf[i]) ;/*左詰めで代入*/
}


/************************************/
/* cvalue()関数 */
/* 1文字の0/1への変換 */
/************************************/
int cvalue(char ch)
{
if(ch=='1') return 1;
else return 0;
}


/************************************/
/* setrule()関数 */
/* ルール表の初期化 */
/************************************/
void setrule(char *arg,int rule[])
{
int ruleno ;/*ルール番号*/
int i ;

/*ルール番号を取得*/
ruleno=atoi(arg) ;
if((ruleno<0)||(255<ruleno)){/*ルール番号が不正*/
fprintf(stderr,"ルール番号が正しくありません(%d) \n",ruleno) ;
exit(1) ;
}
printf("ルール番号 %d :",ruleno) ;
/*ルール表の書き込み*/
for(i=0;i<R;++i){
rule[i]=ruleno%2 ;/*2進数で1の位の値を取り出す*/
ruleno/=2 ;/*左シフト*/
}
/*ルールの出力*/
for(i=R-1;i>=0;--i) printf("%1d",rule[i]) ;
printf("\n") ;

}





/************************************************/
/* coord.cプログラム */
/************************************************/

/* 行列形式のデータを座標形式に変換します */

#include

#define BUFSIZE 1024 /*入力バッファ用配列の長さ*/

/***************************/
/* main関数 */
/***************************/
int main()
{
int lineno=0 ;/*行番号*/
char linebuf[BUFSIZE] ;/*1行入力用の文字配列*/
int i ;

/*初期値を読み込む*/
while(fgets(linebuf,BUFSIZE,stdin)!=NULL){
/*読み取れる間繰り返す*/
if(linebuf[0]=='0'){/*データ領域*/
for(i=0;linebuf[i]!='\0';++i)
if(linebuf[i]=='1') printf("%d %d\n",i,-lineno) ;
/*座標の出力*/
++lineno ;
}
}

return 0 ;
}


 

手順
では実際にプログラムを動かしてみましょう。(以下の手順は、Linux上で、gccコンパイラ、gnuplotがパソコンに入っていることを前提としています。他の環境でも微妙に操作を変えることでうまく動作すると思います。)

0) ca1.c、coord.cが置いてあるフォルダの中に『init.txt』という名前で、125番目だけ1で他はすべて0の合計250文字・1行のテキスト文を作成しておく。例) 000000000000000・・・0001000・・・0000000000000000

1) 端末を開いて、『ca1.c』『coord.c』が置いてある場所へ行き、以下のようにコマンドを打っていく(私が使用しているのはUbuntuなので、端末の初めに表示されるのは ・・・$ )。

$ cd (ca1.c、coord.cが置いてあるディレクトリ名)
$ gcc -o ./ca1 ca1.c
$ gcc -o ./coord coord.c
$./ca1 18 <init.txt | ./coord >fig12out.txt


ここで、2,3行目の gcc のあとの引数 -o はコンパイルして生成される実行ファイルの名前を任意に決めることができるオプションをつけます。使い方は次のようにします。
$ gcc -o ./(実行ファイル名) (プログラム名)

4行目の./ca1 のあとの18という数字は「ルール」で、自分で指定することができます。0から256まで好きな数字をいれてください。それによって描かれる図形が変わってきます。

この結果、座標のデータが入ったテキスト『fig12out.txt』ができあがります。

2) 端末上で

$ gnuplot

と打ちます。その後、端末上に表示されるgnuplotの画面で以下のように打ち込みます。するとグラフ上に図形が描かれます。

gnuplot> plot "fig12out.txt" with points pt 5 ps 0.2 lt 8
pt:点の種類 ps:点のサイズ lt:点、線の色

上にも書いていますが、オプションとして、pt(点の種類)、ps(点のサイズ)、lt(点、線の色)を指定することができます。
ptとltは整数値で指定できます。端末上でいろいろと値を変化させてみて、最も見やすいグラフを作りましょう。




以上です。ソースコードは「小高知宏 『Cによる 数値計算とシミュレーション』 第1版 オーム社」のpp.86ー100、pp.199ー201をほぼ完全に抜粋しました(若干書き換えたところもあります)。

読んでくださった方は、興味があればぜひプログラムを実行してみてください。


関連記事
スポンサーサイト

コメント

非公開コメント

No title

一風変わったセルオートマトンです
http://www7b.biglobe.ne.jp/~gca/
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。