質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

1993閲覧

無限ループしてしまうようになった

pure_storm

総合スコア16

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2017/08/05 08:00

編集2017/08/05 12:18

#解決したいこと
一度はうまくいったのですが、作り直したらなぜか無限ループしてしまうようになってしまいましたのですが、わかる方いますか。コンパイルも通っているのですが。
#追記
#があえて大文字になっていたのはコードの載せ方がよくわからなかったためです。(題名になってしまうため)
新しく入れたubuntu17.04では Segmentation fault (コアダンプ)と出ます。
#エラーメッセージ
特になし
#ソースコード

/************************************************************************** Q学習 **************************************************************************/ #include<stdio.h> #include<time.h> #include<stdlib.h> #include<math.h> // 状態 #define START 0 // 入口 (スタート) #define WOOD 1 // 森 #define LAKE 2 // 湖 #define POND 3 // 池 #define FIELD 4 // 草原 #define GOAL 5 // 宝 (ゴール) // 行動 #define EAST 0 // 東 #define WEST 1 // 西 #define SOUTH 2 // 南 #define NORTH 4 // 北 #define TrialNo 50 // 試行回数 #define StateNum 6 // 状態数 #define ActNum 4 // 行動数 #define Alpha 0.1 // 学習率 #define Gamma 0.9 // 減衰率 #define Reward 10 // 報酬 /********************************************************************* 乱数のシードの生成 **********************************************************************/ void init_rnd() { srand((unsigned int)time(NULL)); } /******************************************************************** 乱数の発生 (0〜1の乱数) ********************************************************************/ double Random() { return((double)rand()/RAND_MAX); } /******************************************************************** ルールの価値の初期化 Qvalue[s][a] : 状態sにおいて行動aを取ることの価値 ********************************************************************/ void init_Q(double Qvalue[StateNum][ActNum]) { int s,a; /* すべての状態と行動の価値を0にする */ /*** この部分を自分で書く ***/ for(s=0;s<StateNum;s++) { for(a=0;a<ActNum;a++) { Qvalue[s][a]=0; } } } /******************************************************************** 行動の選択 (ボルツマン選択) state : 状態 Qvalue[s][a] : 状態sにおいて行動aを取ることの価値 env[s][a] : 状態sにおいて行動aを取ったときに遷移する状態 t : 試行回数 ********************************************************************/ int select_action(int state, double Qvalue[StateNum][ActNum], int env[StateNum-1][ActNum],int t) { double sum; // ルールの価値の合計 int a; // 行動 double r; // 乱数 (0~sumの間の乱数) double border; // 境界線 double T=10; // 温度パラメータ /* 温度パラメータを設定 */ T=T-t; if(T<=1) T=1; /* ルールの価値の合計を計算 その状態で取れない行動(env[state][a]=-1) の価値は合計には含まない */ /*** この部分を自分で書く ***/ for(a=0;a<ActNum;a++) { if(env[state][a]!=-1) { sum+=exp(Qvalue[state][a]/T); } } /* 0~sumの乱数を生成 */ r = Random()*sum; border=0; for(a=0;a<ActNum;a++){ /* 取ることのできる行動の中から行動を選択 */ if(env[state][a]!=-1){ border += exp(Qvalue[state][a]/T); } /* 選択された行動を返す */ if(r<=border){ return a; } } } /******************************************************************** ルールの価値の更新 Qvalue[s][a] : 状態sにおいて行動aを取ることの価値 p_state : 直前の状態 act : 行動 state : 状態 (行動後の状態) r : 報酬 ********************************************************************/ void update_Q(double Qvalue[StateNum][ActNum], int p_state, int act, int state, int r) { int a; double max; // 行動後の状態から取ることのできる行動の中での価値の最大値 /* 取ることのできる行動に関する価値の中で最大値を求める */ /*** この部分を自分で書く ***/ for(a=0;a<ActNum;a++) { if(max<Qvalue[state][a]) { max=Qvalue[state][a]; } } /* 状態p_stateにおいて行動actをとることの価値を更新 */ /*** この部分を自分で書く ***/ Qvalue[p_state][act]=Qvalue[p_state][act]+Alpha*(r+Gamma*max-Qvalue[p_state][act]); } /************************************************************************** メインプログラム **************************************************************************/ int main() { int t; int s,a; int act; // 行動 int p_state; // 直前の状態 int state; // 状態 double Qvalue[StateNum][ActNum]; // ルールの価値 // 環境 (状態の遷移) 東 西 南 北 int env[StateNum-1][ActNum]={{WOOD, -1, POND, -1}, // 入口 {LAKE, START, FIELD,-1}, // 森 {-1, WOOD, GOAL, -1}, // 湖 {FIELD,-1, -1, START}, // 池 {-1 ,POND, -1, WOOD}}; // 草原 int count; // エピソードの長さ char *states[StateNum]={"入口","森","湖","池","草原","宝"}; // 状態(表示用) char *acts[ActNum]={"東","西","南","北"}; // 行動(表示用) FILE *fp; // ファイルポインタ /* 結果保存用のファイル(result.dat)をオープン */ if((fp=fopen("result.dat","w"))==NULL){ printf("main() : Cannot open \"result.dat\"\n"); exit(1); } init_rnd(); /* 乱数の初期化 */ init_Q(Qvalue); /* ルールの価値の初期化 */ /* TrialNo回の試行を繰り返す */ for(t=0;t<TrialNo;t++){ printf("[%d]",t); state = START; /* 状態を初期化(STARTに設定) */ count=0; /* エピソードの長さを0で初期化 */ /* ゴールに到達するまで繰り返す */ while(state!=GOAL){ act=select_action(state,Qvalue,env,t); /* 行動を選択 */ p_state=state; /* 状態を保存 */ state=env[p_state][act]; /* 行動することにより状態が遷移 */ /* ゴールに到達したら報酬を取得し、ルールの価値を更新 */ if(state==GOAL){ update_Q(Qvalue,p_state,act,state,Reward); } /* ルールの価値を更新(ゴール以外では報酬は0) */ else{ update_Q(Qvalue,p_state,act,state,0); } /* 状態と行動を画面に表示 */ printf("%s==>(%s)==>",states[p_state],acts[act]); /* エピソードの長さを1増やす */ count++; } /* 最終的な状態を画面に表示 */ printf("%s\n",states[state]); /* 試行回数とエピソードの長さをファイルに出力 */ fprintf(fp,"%d %d\n",t,count); } /* ファイルをクローズ */ fclose(fp); /* 最終的なルールの価値保存用のファイルをオープン */ if((fp=fopen("Q.dat","w"))==NULL) { printf("main() : Cannot open \"Q.dat\"\n"); exit(1); } /* ルールの価値をファイルに書き出す */ fprintf(fp," 東 西 南 北\n"); for(s=0;s<StateNum;s++) { fprintf(fp,"%s\t",states[s]); for(a=0;a<ActNum;a++) { fprintf(fp,"%6.3lf\t",Qvalue[s][a]); } fprintf(fp,"\n"); } /* ファイルをクローズ */ fclose(fp); }

#環境
ubuntu16.04
コンパイル
gcc ファイル名.c -lm
実行結果
入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>入口==>(�,��)==>��

#環境
ubuntu17.04
コンパイル
gcc ファイル名.c -lm
実行結果
[0]入口==>(南)==>池==>(東)==>草原==>(西)==>池==>(北)==>入口==>(東)==>森==>(南)==>草原==>(北)==>森==>(西)==>入口==>(東)==>森==>(西)==>入口==>(東)==>森==>(南)==>草原==>(北)==>森==>(東)==>湖==>(南)==>宝
[1]入口==>(南)==>池==>(北)==>入口==>(東)==>森==>(南)==>草原==>(西)==>池==>(北)==>入口==>(東)==>森==>(西)==>入口==>(南)==>池==>(北)==>入口==>(南)==>池==>(東)==>草原==>(西)==>池==>(北)==>入口==>(南)==>池==>(東)==>草原==>(北)==>森==>(東)==>湖==>(南)==>宝
[2]入口==>(東)==>森==>(西)==>入口==>(東)==>森==>(東)==>湖==>(南)==>宝
[3]入口==>(南)==>池==>(北)==>入口==>(東)==>森==>(南)==>草原==>(西)==>池==>(東)==>草原==>(北)==>森==>(東)==>湖==>(西)==>森==>(南)==>草原==>(西)==>池==>(東)==>草原==>(西)==>池==>(東)==>草原==>(北)==>森==>(東)==>湖==>(南)==>宝
[4]入口==>(南)==>池==>(東)==>草原==>(北)==>森==>(西)==>入口==>(東)==>森==>(南)==>草原==>(北)==>森==>(東)==>湖==>(南)==>宝
[5]入口==>(東)==>森==>(南)==>草原==>(北)==>森==>(西)==>入口==>(南)==>池==>(北)==>入口==>(東)==>森==>(南)==>草原==>(北)==>森==>(南)==>草原==>(北)==>森==>(東)==>湖==>(南)==>宝
[6]入口==>(南)==>池==>(北)==>入口==>(東)==>森==>(東)==>湖==>(南)==>宝
[7]入口==>(南)==>池==>(北)==>入口==>(南)==>池==>(北)==>入口==>(東)==>森==>(南)==>草原==>(北)==>森==>(南)==>草原==>(西)==>池==>(北)==>入口==>(南)==>池==>(東)==>草原==>(西)==>池==>(東)==>草原==>(西)==>池==>(北)==>入口==>(南)==>池==>(北)==>入口==>(南)==>池==>(東)==>草原==>(西)==>池==>(東)==>草原==>(北)==>森==>(東)==>湖==>(南)==>宝
[8]入口==>(南)==>池==>(東)==>草原==>(西)==>池==>(北)==>入口==>(南)==>池==>(北)==>入口==>(南)==>池==>(東)==>草原==>(北)==>森==>(東)==>湖==>(南)==>宝
[9]入口==>(南)==>池==>(東)==>草原==>(北)==>森==>(東)==>湖==>(南)==>宝
Segmentation fault (コアダンプ)
#追記
ubuntu16.04ではうまくいきませんが、新たに入れたubuntu17,04ではSegmentation fault (コアダンプ)と出ます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hotta

2017/08/05 08:52

コード全体を範囲していて<code>を押してください。
guest

回答2

0

/* ゴールに到達するまで繰り返す */
while(state!=GOAL){

この中でstateの値が変わっていないように思いますが?

投稿2017/08/05 08:33

maiko0318

総合スコア876

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yumetodo

2017/08/05 08:52

ん?それは state=env[p_state][act]; で変わっているのでは
maiko0318

2017/08/05 09:41

とりあえず、各ループのところでprintにてどこを実行しているかわかるようにしましょう。 state=env[p_state][act]; このあとstateが何になっているかを含めて。
guest

0

ベストアンサー

まあまずそもそもコンパイルエラーになっていたのといらない関数があったのを直して変数のスコープが無駄にでかいのを小さくして見たのがこれです

c

1/********************************************************************** 2Q学習 3**********************************************************************/ 4#include <stdio.h> 5#include <time.h> 6#include <stdlib.h> 7#include <math.h> 8 9// 状態 10#define START 0 // 入口 (スタート) 11#define WOOD 1 // 森 12#define LAKE 2 // 湖 13#define POND 3 // 池 14#define FIELD 4 // 草原 15#define GOAL 5 // 宝 (ゴール) 16 17// 行動 18#define EAST 0 // 東 19#define WEST 1 // 西 20#define SOUTH 2 // 南 21#define NORTH 4 // 北 22 23#define TRIALNO 50 // 試行回数 24#define STATENUM 6 // 状態数 25#define ACTNUM 4 // 行動数 26 27#define ALPHA 0.1 // 学習率 28#define GAMMA 0.9 // 減衰率 29 30#define REWARD 10 // 報酬 31 32/***************************************************************** 33乱数のシードの生成 34******************************************************************/ 35void init_rnd() 36{ 37 srand((unsigned int)time(NULL)); 38} 39 40/**************************************************************** 41乱数の発生 (0〜1の乱数) 42****************************************************************/ 43double Random() 44{ 45 return((double)rand()/RAND_MAX); 46} 47 48/**************************************************************** 49行動の選択 (ボルツマン選択) 50state : 状態 51Qvalue[s][a] : 状態sにおいて行動aを取ることの価値 52env[s][a] : 状態sにおいて行動aを取ったときに遷移する状態 53t : 試行回数 54****************************************************************/ 55int select_action(int state, 56const double Qvalue[STATENUM][ACTNUM], 57const int env[STATENUM-1][ACTNUM],int t) 58{ 59 double sum = 0.0; // ルールの価値の合計 60 int a; // 行動 61 double r; // 乱数 (0~sumの間の乱数) 62 double border; // 境界線 63 double T=10; // 温度パラメータ 64 65 /* 温度パラメータを設定 */ 66 T=T-t; 67 if(T<=1) T=1; 68 69 /* ルールの価値の合計を計算 70 その状態で取れない行動(env[state][a]=-1) 71 の価値は合計には含まない */ 72 /* この部分を自分で書く */ 73 for(a=0;a<ACTNUM;a++) 74 { 75 if(env[state][a]!=-1) 76 { 77 sum+=exp(Qvalue[state][a]/T); 78 } 79 } 80 81 /* 0~sumの乱数を生成 */ 82 r = Random()*sum; 83 border=0; 84 for(a=0;a<ACTNUM;a++){ 85 /* 取ることのできる行動の中から行動を選択 */ 86 if(env[state][a]!=-1){ 87 border += exp(Qvalue[state][a]/T); 88 } 89 /* 選択された行動を返す */ 90 if(r<=border){ 91 return a; 92 } 93 } 94 exit(2); 95} 96 97/**************************************************************** 98ルールの価値の更新 99Qvalue[s][a] : 状態sにおいて行動aを取ることの価値 100p_state : 直前の状態 101act : 行動 102state : 状態 (行動後の状態) 103r : 報酬 104****************************************************************/ 105void update_Q(double Qvalue[STATENUM][ACTNUM], 106int p_state, int act, int state, int r) 107{ 108 int a; 109 double max; // 行動後の状態から取ることのできる行動の中での価値の最大値 110 111 /* 取ることのできる行動に関する価値の中で最大値を求める */ 112 /* この部分を自分で書く */ 113 for(a=0;a<ACTNUM;a++) 114 { 115 if(max<Qvalue[state][a]) 116 { 117 max=Qvalue[state][a]; 118 } 119 } 120 121 /* 状態p_stateにおいて行動actをとることの価値を更新 */ 122 /* この部分を自分で書く */ 123 Qvalue[p_state][act]=Qvalue[p_state][act]+ALPHA*(r+GAMMA*max-Qvalue[p_state][act]); 124} 125 126/********************************************************************** 127メインプログラム 128**********************************************************************/ 129int main() 130{ 131 int t; 132 int s,a; 133 double Qvalue[STATENUM][ACTNUM] = { { 0 } }; // ルールの価値 134 // 環境 (状態の遷移) 東 西 南 北 135 int env[STATENUM-1][ACTNUM]={ 136 {WOOD, -1, POND, -1}, // 入口 137 {LAKE, START, FIELD,-1}, // 森 138 {-1, WOOD, GOAL, -1}, // 湖 139 {FIELD,-1, -1, START}, // 池 140 {-1 ,POND, -1, WOOD} // 草原 141 }; 142 const char *states[STATENUM]={"入口","森","湖","池","草原","宝"}; // 状態(表示用) 143 const char *acts[ACTNUM]={"東","西","南","北"}; // 行動(表示用) 144 FILE *fp; // ファイルポインタ 145 146 /* 結果保存用のファイル(result.dat)をオープン */ 147 if((fp=fopen("result.dat","w"))==NULL){ 148 printf("main() : Cannot open \"result.dat\"\n"); 149 exit(1); 150 } 151 152 init_rnd(); /* 乱数の初期化 */ 153 154 /* TrialNo回の試行を繰り返す */ 155 for(t=0;t<TRIALNO;t++){ 156 int state = START; /* 状態を初期化(STARTに設定) */ 157 int episode_len=0; /* エピソードの長さを0で初期化 */ 158 printf("[%d]",t); 159 /* ゴールに到達するまで繰り返す */ 160 while(state!=GOAL){ 161 int act=select_action(state,Qvalue,env,t); /* 行動を選択 */ 162 int p_state=state; /* 状態を保存 */ 163 state=env[p_state][act]; /* 行動することにより状態が遷移 */ 164 /* ゴールに到達したら報酬を取得し、ルールの価値を更新 */ 165 if(state==GOAL){ 166 update_Q(Qvalue,p_state,act,state,REWARD); 167 } 168 /* ルールの価値を更新(ゴール以外では報酬は0) */ 169 else{ 170 update_Q(Qvalue,p_state,act,state,0); 171 } 172 /* 状態と行動を画面に表示 */ 173 printf("%s==>(%s)==>",states[p_state],acts[act]); 174 /* エピソードの長さを1増やす */ 175 episode_len++; 176 } 177 /* 最終的な状態を画面に表示 */ 178 printf("%s\n",states[state]); 179 /* 試行回数とエピソードの長さをファイルに出力 */ 180 fprintf(fp,"%d %d\n",t,episode_len); 181 } 182 /* ファイルをクローズ */ 183 fclose(fp); 184 185 /* 最終的なルールの価値保存用のファイルをオープン */ 186 if((fp=fopen("Q.dat","w"))==NULL) 187 { 188 printf("main() : Cannot open \"Q.dat\"\n"); 189 exit(1); 190 } 191 192 /* ルールの価値をファイルに書き出す */ 193 fprintf(fp," 東 西 南 北\n"); 194 for(s=0;s<STATENUM;s++) 195 { 196 fprintf(fp,"%s\t",states[s]); 197 for(a=0;a<ACTNUM;a++) 198 { 199 fprintf(fp,"%6.3lf\t",Qvalue[s][a]); 200 } 201 fprintf(fp,"\n"); 202 } 203 204 /* ファイルをクローズ */ 205 fclose(fp); 206 207 return 0; 208}

https://wandbox.org/permlink/Rxaq3n01UxZYBjX9

実行結果を見れば明白なように、select_action関数内で取るべき行動が何もなかった場合に何を返すべきか判断できなかったのでとりあえずexit(2);した部分に引っかかっています。

ここを直せばいいかと思われます。

投稿2017/08/05 09:56

yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rubato6809

2017/08/06 09:25

私の手元ではselect_action関数が-1を返していました。0~3の値を返すべきところ、for文を回りきって(即ち、return a;することなく)、ゴミの値を返したに違いありません。まさに exit(2); を入れたところです。 for文を回りきった場合、何をreturnすべきか、を含めて、この関数の処理を見直すことが第一だと思います。 この関数が正しい値を返さないなら、while(state!=GOAL){ のループが正しい動作をしないのは、無理からぬことだと思います。
pure_storm

2017/08/10 17:31

的確なお答えありがとうございました。もう少し修正して頑張ってみます。
yumetodo

2017/08/10 17:33

教訓:コンパイラにはありったけの警告表示オプションをつけよう 今回の件は普通にWarning出てたので。 gcc/clangなら -Wall -Wextra MSVCなら/W4 はつけておきたいところ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問