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

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

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

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

Q&A

解決済

2回答

3312閲覧

二次元配列のexcelへの出力ができません

pom_pom

総合スコア13

C

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

0グッド

0クリップ

投稿2015/06/30 12:08

編集2015/06/30 12:23

こんにちは.オーム社の「ロボットインテリジェンス」という本でC言語と強化学習を学び始めました.
その本の中の,迷路最適経路を求めるQ学習のサンプルプログラムを参考に自分で(5,7)から(5,1)まで1ステップずつ動く障害物を付け加えてみました.
きちんと動作しているのかを確かめるために,試行回数50回ごとに設定した迷路maze[x][y]とQ値Qtable[s][a]という二次元配列をexcelに出力しようと思ったのですが,上手くいきません.
無限ループに入ってしまったようです.

申し訳ありませんが,どのようにすればいいか教えてください.
よろしくお願いします.

長いですが以下,ソースコードです.

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

int move(int a, int &x, int &y, int x_size);
int xy2s(int x, int y, int x_size);
int select_action(int s, int num_a, double** Qtable);
double max_Qval(int s, int num_a, double** Qtable);
int epsilon_greedy(int epsilon, int s, int num_a, double** Qtable);
int k;

int main()
{
FILE *file;
file = fopen("Qtable.csv", "w");

int x_size;//x軸方向の迷路の大きさ(x_size=10の時には,xは0から9の値をとる) int y_size; double alpha, gamma;//α学習係数とγ減衰係数 int x, y, x_init, y_init; int **maze; int num_step;//一試行におけるQ値の更新回数 int num_trial;//試行回数 int i, j; int a, s, sd;//行動,状態,行動の実行によって遷移する状態 int num_a;//行動数 int num_s;//状態数 double **Qtable; int reward;//報酬 double Qmax;//Q値の最大値 int epsilon; //int k; //int u; //パラメータの設定 alpha = 0.5; gamma = 0.9; epsilon = 10; x_size = 10; y_size = 9; x_init = 1; y_init = 1; num_step = 500; num_trial = 55; num_a = 4;//行動の数 num_s = x_size*y_size;//状態の数 //乱数の初期化 srand((unsigned)time(NULL)); //Q-table Qtable = new double*[num_s]; for (i = 0; i < num_s; i++){ Qtable[i] = new double[num_a]; } //Q-tableの初期化 for (i = 0; i < num_s; i++){ for (j = 0; j < num_a; j++){ Qtable[i][j] = 0; } } //迷路 maze = new int*[x_size]; for (i = 0; i < x_size; i++){ maze[i] = new int[y_size]; } //迷路の初期化(迷路の周りに壁を設定) for (i = 0; i < x_size; i++){ for (j = 0; j < y_size; j++){ if (i == 0 || j == 0 || i == (x_size - 1) || j == (y_size - 1)){ maze[i][j] = -1; } else{ maze[i][j] = 0; } } } //壁の設定 maze[2][2] = -1; maze[3][2] = -1; maze[6][3] = -1; maze[7][3] = -1; maze[8][3] = -1; maze[2][6] = -1; maze[2][7] = -1; maze[3][6] = -1; maze[6][7] = -1; //報酬の設定 maze[8][6] = 10; //for (i = 0; i < x_size; i++){ // for (j = 0; j < y_size; j++){ // //printf("%3d", maze[i][j]);

// fprintf(file, "%3f" ,Qtable[i][j]);
// }
// printf("\n");
//}

//初期設定 x = x_init; y = y_init; s = xy2s(x, y, x_size); /******************************** * 試行開始 * ********************************/ //学習開始 for (i = 0; i < num_trial; i++){ for (j = 0; j < num_step; j++){ //Q値の更新の複数回更新 for(k = 7; 1 <= k ; --k){ maze[5][k]=-5; a = epsilon_greedy(epsilon, s, num_a, Qtable);//行動選択(ε-greedy法) sd = move(a, x, y, x_size);//エージェント移動 選択された行動に合わせてエージェントが移動,移動後の状態をsdに格納 reward = maze[x][y];//移動後の場所に設定している報酬をrewardに代入 Qmax = max_Qval(sd, num_a, Qtable);//遷移先の状態におけるQ値の最大値を求める Qtable[s][a] = Qtable[s][a] + alpha * ((double)reward + gamma * Qmax - Qtable[s][a]); //試行の成否の判断 //壁にぶつかったら"失敗"と表示して,エージェントを初期位置に戻して試行を終了,次の試行に移る //ゴールに到達した場合,"成功"と表示して,エージェントを初期位置に戻して試行を終了,次の試行に移る //どちらでもない場合,現在の状態に遷移先の状態を代入し,試行を継続する if (reward < 0){ //失敗 x = x_init; y = y_init; s = xy2s(x, y, x_size); maze[5][k]=0; goto OUT; } else if (reward > 0){ //成功 x = x_init; y = y_init; s = xy2s(x, y, x_size); maze[5][k]=0; goto OUT; } else{ //続行 s = sd; maze[5][k] = 0; goto OUT2; } }

OUT2:;
}
OUT:;
}

//政策の表示 for (x = 0; x<x_size; x++){ for (y = 0; y<y_size; y++){ s = xy2s(x, y, x_size); Qmax = max_Qval(s, num_a, Qtable); if (Qmax == 0){ printf("%3d", maze[x][y]); } else{ a = select_action(s, num_a, Qtable); if (a == 0){ printf(" →"); } else if (a == 1){ printf(" ↓"); } else if (a == 2){ printf(" ←"); } else{ printf(" ↑"); } } } printf("\n"); }

//ここでQtableの状態を出力したい
if (i=i+50){
for (x=0;x<x_size;x++){
for (y=0;y<y_size;y++){
for(a=0;a<4;a++){
s = x + y * x_size;
fprintf(file,"%f",Qtable[s][a]);
}
}
}
}
//ここまで

for (i = 0; i<num_s; i++){ delete[] Qtable[i]; } delete[] Qtable; for (i = 0; i<x_size; i++){ delete[] maze[i]; } delete[] maze; //ファイルクローズ fclose(file); return 0;

}

int move(int a, int &x, int &y, int x_size){

if (a == 0){ y = y + 1; } else if (a == 1){ x = x + 1; } else if (a == 2){ y = y - 1; } else{ x = x - 1; } int sd; sd = xy2s(x, y, x_size); return sd;

}

int xy2s(int x, int y, int x_size){
int s;
s = x + y * x_size;
return s;
}

/*************************

  • 行動を選択する為の関数 *

**********************/
int select_action(int s, int num_a, double
Qtable){//宣言(状態s,行動数num_a,Qtableで,Q値が最大になる行動を返す
double max;
int i = 0;
int
i_max = new int[num_a];//最大値を持つQ値の行動を保存する為の変数
int num_i_max = 1;
int a;

i_max[0] = 0;//行動が0の時を初期値に max = Qtable[s][0]; //最大値の検索(大きなQ値が見つかると,新たな最大値として入力,num_i_maxを1に戻す) for (i = 1; i<num_a; i++){ if (Qtable[s][i]>max){ max = Qtable[s][i]; num_i_max = 1; i_max[0] = i; } else if (Qtable[s][i] == max){ num_i_max++; i_max[num_i_max - 1] = i; } } a = i_max[rand() % num_i_max];//最大値を持つ行動からランダムで1つを選択 return a;

}

//最大値を求める関数
double max_Qval(int s, int num_a, double** Qtable){
double max;
int i = 0;

max = Qtable[s][0];//Q[s][0]をmaxの初期値に設定 //maxとQの値を比較していく↓ for (i = 1; i<num_a; i++){ if (Qtable[s][i]>max){ max = Qtable[s][i];//もしQ > maxの時,maxにQを代入 } } return max;

}

//ε-greedy法の関数

int epsilon_greedy(int epsilon, int s, int num_a, double** Qtable){
int a;
if (epsilon > rand() % 100){
//無作為に行動を選択
a = rand() % num_a;
//printf("無作為に選択\n");
}
else{
//最大のQ値を持つ行動を選択
a = select_action(s, num_a, Qtable);
}
return a;
}

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

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

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

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

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

guest

回答2

0

ベストアンサー

プログラムで問題なのではないかと思われる点を書きます。
その辺りを修正する事で、問題の一部は解決するのではないでしょうか。

1) 「excelへの出力」と書かれていますが、"Qtable.csv"というファイル名から、CSV形式のテキストファイルに出力しようとしているのではないでしょうか。
CSV形式は、項目の列(vector)を, (comma)で区切った(Separated)テキストファイルの形式です。
(CSVは、Comma Separated Vectorの頭文字を連ねたものです)

2)csv形式でテキストファイルに書き込むのであれば、

lang

1 for (x=0;x<x_size;x++){ 2 for (y=0;y<y_size;y++){ 3 for(a=0;a<4;a++){ 4 s = x + y * x_size; 5 if a<3 { 6 fprintf(file,"%f,",Qtable[s][a]); } //最初の3項は、後に区切りのカンマをつける 7 else { 8 fprintf(file,"%f\n",Qtable[s][a]); } //4項目の後は、改行 9 } 10 }

というような感じで、区切りのカンマ(,)や改行(\n)を適宜出力する必要があります。

投稿2015/07/01 04:44

coco_bauer

総合スコア6915

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

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

0

(コードを読んでいる時間がないので)一般的なデバッグの仕方についてコメントいたします。

まず、デバッガは使用できる環境でしょうか?
Visual Studio などを使っているのであれば、デバッガを使ってみることをお勧めします。
途中で一時停止させて計算結果を確認したりできます。お勉強を進めるうえでも役に立つと思います。

デバッグの手始めは「どこまでは動いているか」を大まかに確認していくことです。
関数単位くらいであたりをつけて、徐々に絞り込みをしていきます。
問題個所がみつかったら、そこから遡って原因を探していきます。

> 無限ループに入ってしまったようです.
ということは、プログラムがずっと動作したまま、あるいはハングアップした状態でしょうか?
forループが多数あるようですね。終了条件が正しいか確認してみてください。
ループの終了条件、if文の条件、はバグの原因になりやすいものです。

投稿2015/07/17 02:49

mie

総合スコア229

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問