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

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

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

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

Q&A

1回答

2038閲覧

Q学習について

mikamikan

総合スコア16

C

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

0グッド

1クリップ

投稿2015/12/03 19:52

###前提・実現したいこと
強化学習(Q学習)でスタート地点からゴール地点までの最適な道のりを求めようとしています。
###発生している問題・エラーメッセージ
今、プログラムを50回回しても答えが出なかったら次の試行に行くようにしているのですが、次の試行に移った時にxy座標が更新されません。
また、ネットなどで調べてみると、最終的にQ学習は答えが収束すると書いてあったのですが、プログラムの試行回数を増やしても答えが収束しません。
この2つに悩んでいます。

お力を貸していただけると嬉しいです。
よろしくお願いします。

###ソースコード

C

1#define _CRT_SECURE_NO_WARNINGS 2#include <stdio.h> 3#include <stdlib.h> 4#include <time.h> 5#define _USE_MATH_DEFINES 6#include <math.h> 7 8typedef struct car { 9 double x; //現在位置x 10 double y; //現在位置y 11 double dx; //次の位置x 12 double dy; //次の位置y 13 double max_x; //xの最大値 14 double max_y; //yの最大値 15 int s; 16 int sd; 17 int L = 50; 18}agent; 19 20int move(car *agent, int a, int sd); 21int select_action(car *agent, int num_a, double** Qtable); 22double max_Qval(car *agent, int num_a, double** Qtable); 23int epsilon_greedy(car *agent, int epsilon, int num_a, double** Qtable); 24int xy2s(car *agent, int a); 25 26int main() { 27 FILE *file; 28 file = fopen("car.csv", "w"); 29 car agent; 30 31 int num_step; //ステップ数 32 int num_trial; //試行回数 33 int i, j; 34 int a; 35 double alpha, gamma; 36 37 int reward; //報酬 38 39 int num_a; //行動 40 int num_s; //状態 41 double **Qtable; 42 double Qmax; 43 int epsilon; 44 45 //パラメータの設定 46 alpha = 0.5; 47 gamma = 0.9; 48 epsilon = 10; 49 50 num_step = 50; 51 num_trial =500; 52 53 num_a = 4; 54 55 //エリアの数 56 num_s = 25; 57 int sepa = 5; 58 59 //乱数の初期化 60 srand((unsigned)time(NULL)); 61 62 //Q-table 63 Qtable = new double*[num_s]; 64 for (i = 0; i < num_s; i++) { 65 Qtable[i] = new double[num_a]; 66 } 67 68 //Q-tableの初期化 69 for (i = 0; i < num_s; i++) { 70 for (j = 0; j < num_a; j++) { 71 Qtable[i][j] = 0; 72 } 73 } 74 75 //agentの初期設定 76 agent.x = 25.0; 77 agent.y = 25.0; 78 agent.max_x = 250.0; 79 agent.max_y = 250.0; 80 81 agent.s = (int)agent.x / agent.L + (int)agent.y / agent.L * sepa; 82 83 //学習開始 84 for (i = 0; i < num_trial; i++) { 85 fprintf(file, "i=%d\n", i); 86 for (j = 0; j < num_step; j++) { 87 //fprintf(file, "j=%d\n", j); 88 flag: 89 a = epsilon_greedy(&agent, epsilon, num_a, Qtable);//どの方向に動くか決める 90 agent.s = (int)agent.x / agent.L + (int)agent.y / agent.L * sepa;//現在のarea 91 92 agent.sd = move(&agent, a, agent.s); 93 printf("%f,%f\n", agent.x, agent.y); 94 95 //ここで障害物の設定 96 //障害物があるagent.sに入るとrewardに-10が入り試行を終了する 97 //Goalに入るとrewardに+10が入り試行を終了 98 //その他はreward=0なのでそのまま続行 99 100 if (agent.s == 20) { 101 reward = 1000; 102 } 103 else if(agent.s == 15) { 104 reward = -10; 105 } 106 else { 107 reward = 0; 108 } 109 if (agent.dx < 0 || agent.dx > agent.max_x || agent.dy < 0 || agent.dy > agent.max_y) { 110 goto flag; 111 } 112 113 Qmax = max_Qval(&agent, num_a, Qtable); 114 Qtable[agent.s][a] = (1 - alpha)*Qtable[agent.s][a] + alpha * ((double)reward + gamma*Qmax);//?? 115 116 fprintf(file, "%f,%f,a=%d,s=%d,sd=%d,%d\n", agent.x, agent.y, a, agent.s, agent.sd,reward); 117 118 if (reward < 0) { 119 //失敗 120 agent.x = 25.0; 121 agent.y = 25.0; 122 agent.s = (int)agent.x / agent.L + (int)agent.y / agent.L * sepa; 123 break; 124 } 125 else if (reward > 0) { 126 //成功 127 agent.x = 25.0; 128 agent.y = 25.0; 129 agent.s = (int)agent.x / agent.L + (int)agent.y / agent.L * sepa; 130 break; 131 } 132 else { 133 //続行 134 agent.x = agent.dx; 135 agent.y = agent.dy; 136 agent.s = agent.sd; 137 } 138 } 139 } 140 141 fclose(file); 142 return 0; 143} 144 145int move(car *agent, int a, int sd) { 146 147 switch (a) { 148 case 0://↑ 149 agent->dy = agent->y + 50.0; 150 agent->dx = agent->x; 151 break; 152 case 1://→ 153 agent->dx = agent->x + 50.0; 154 agent->dy = agent->y; 155 break; 156 case 2://↓ 157 agent->dy = agent->y - 50.0; 158 agent->dx = agent->x; 159 break; 160 case 3://← 161 agent->dx = agent->x - 50.0; 162 agent->dy = agent->y; 163 break; 164 } 165 //sdはアクションが起こった後のagent.sを表す 166 agent->sd = (int)agent->dx / agent->L + (int)agent->dy / agent->L * 5; 167 return agent->sd; 168} 169 170 171int select_action(car *agent, int num_a, double**Qtable) { 172 double max; 173 int i = 0; 174 int* i_max = new int[num_a]; 175 int num_i_max = 1; 176 int a; 177 i_max[0] = 0; 178 max = Qtable[agent->s][0]; 179 180 for (i = 0; i < num_a; i++) { 181 if (Qtable[agent->s][i] > max) { 182 num_i_max = 1; 183 i_max[0] = i; 184 } 185 else if (Qtable[agent->s][i] == max) { 186 num_i_max++; 187 i_max[num_i_max - 1] = i; 188 } 189 } 190 191 a = i_max[rand() % num_i_max]; 192 return a; 193} 194 195double max_Qval(car *agent, int num_a, double** Qtable) { 196 double max; 197 int i = 0; 198 199 max = Qtable[agent->s][0];//? 200 for (i = 0; i < num_a; i++) {//1? 201 if (Qtable[agent->s][i] > max) { 202 max = Qtable[agent->s][i]; 203 } 204 } 205 return max; 206} 207 208int epsilon_greedy(car *agent, int epsilon, int num_a, double** Qtable) { 209 int a; 210 if (epsilon > rand() % 100) { 211 a = rand() % num_a; 212 } 213 else { 214 a = select_action(agent, num_a, Qtable); 215 } 216 return a; 217}

###補足情報(言語/FW/ツール等のバージョンなど)

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

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

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

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

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

WoodenHamlet

2015/12/04 01:46

typedef で agent にしてるのに car 型で定義してしかも変数名が agent なのはなぜ?
mikamikan

2015/12/04 03:39 編集

すみません。初心者なものでネットで調べたものを使いました。 少し見づらくてすみません。 typedef struct employee { char name\\\[12\\\]; double hours; int wage; } EMPLOYEE; EMPLOYEE yamada; // EMPLOYEE 型の変数 yamada を作成
WoodenHamlet

2015/12/04 04:11

その例では、 ① struct employee 型を typedef によって EMPLOYEE として使えるようにしている(別名) ②EMPLOYEE 型の変数 yamada を定義 Cでは本来 struct employee yamada と、構造体変数の宣言時は頭に struct を付けなければならないのを、「EMPLOYEE」=「struct employee」として簡単に書けるようにしているのです。 たいして質問者さんのコードでは、car で変数型を宣言している(C++でなら許されるんじゃないかな?)、typedef で別名に指定した agent を変数名にしているのでわかりづらいコードになってしまっているように思います。 一度 typedef を調べてみてはいかがでしょうか
guest

回答1

0

学習については門外漢なんだけど、ざっとコード見た感じの思ったこと。

構造体の宣言に初期値って宣言できたっけ?

C++

1class AGENT { 2public: 3AGENT():L(50){}; 4 double x; //現在位置x 5 double y; //現在位置y 6 double dx; //次の位置x 7 double dy; //次の位置y 8 double max_x; //xの最大値 9 double max_y; //yの最大値 10 int s; 11 int sd; 12 int L; 13};

new したら delete

C++

1 //Q-table 2 Qtable = new double*[num_s]; 3 for (i = 0; i < num_s; i++) { 4 Qtable[i] = new double[num_a]; 5 } 6// ここにコード 7 for (i=0; i< num_s; ++i) 8 { 9 delete[] Qtable[i]; 10 } 11 delete[] Qtable; 12}

他の個所でも配列を new でメモリ確保しているけど、delete してなさそうな感じがする。

これは見当違いかもしれないけど、ココは括弧で括らなくてもいい?

C++

1 //sdはアクションが起こった後のagent.sを表す 2// agent->sd = (int)agent->dx / agent->L + (int)agent->dy / agent->L * 5; 3 agent->sd = ((int)agent->dx / agent->L + (int)agent->dy / agent->L )* 5; 4 return agent->sd;

投稿2015/12/04 06:54

WoodenHamlet

総合スコア306

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

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

mikamikan

2015/12/05 02:26

回答ありがとうございます。 知らなかったので調べてみたところ構造体の宣言時に初期値を宣言するのはダメっぽいですね。 また、deleteもしていませんでした。 あと、agent->sd = (int)agent->dx / agent->L + (int)agent->dy / agent->L * 5;のところですが、空間座標の分割というサイトを参考にしたxy座標を用いて現在のエリアを算出する式なので括弧でくくらなくても大丈夫です。 自分では気づけないところがたくさんありました。 ありがとうございます!
WoodenHamlet

2015/12/07 08:05

reword による分岐で j ループの外に出てるけど、i ループの中でまだまわっているのは狙い通りの動きかな? goto flag; が、j を更新していないのは正しい?(ref. continue 文) 理想通りの動きをしたとき、どんな標準出力でどんな出力ファイルになるべきかがわかるともっと回答しやすいかな、と思いますよ。私もこのサイトは初心者なので偉そうなことは言えませんがw
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問