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

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

ただいまの
回答率

87.48%

Q学習の問題とC言語の問題

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 3,777

score 16

前提・実現したいこと

C言語とQ学習のプログラミング問題です。
プログラミングが苦手で手詰まり状態です。ヒントでもいいので教えてください。

発生している問題・エラーメッセージ

穴埋め部分がわかりません

わからない部分

どうしたらいいかわからない状態です

その1

ルールの価値の初期化

Qvalue[s][a] : 状態sにおいて行動aを取ることの価値
****************************************************************/
void init_Q(double Qvalue[StateNum][ActNum])
{
int s,a;
/* すべての状態と行動の価値を0にする */
/* この部分を自分で書く */
}
その2
 /* 温度パラメータを設定 */
 T=T-t;
 if(T<=1) T=1;
 /* ルールの価値の合計を計算 
    その状態で取れない行動(env[state][a]=-1)
    の価値は合計には含まない */
 /*** この部分を自分で書く ***/
その3
/********************************************************************
 ルールの価値の更新
   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; // 行動後の状態から取ることのできる行動の中での価値の最大値
 /* 取ることのできる行動に関する価値の中で最大値を求める */
 /*** この部分を自分で書く ***/
 /* 状態p_stateにおいて行動actをとることの価値を更新 */
 /*** この部分を自分で書く ***/
}

該当のソースコード

/**************************************************************************
  Q学習
**************************************************************************/
#include<stdio.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にする */
 /*** この部分を自分で書く ***/
}
/********************************************************************
 行動の選択 (ボルツマン選択)
   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)
    の価値は合計には含まない */
 /*** この部分を自分で書く ***/
 /* 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; // 行動後の状態から取ることのできる行動の中での価値の最大値
 /* 取ることのできる行動に関する価値の中で最大値を求める */
 /*** この部分を自分で書く ***/
 /* 状態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);
}

試したこと

理解できないところが多くて、手が付けられない状態です

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

Linax
VMware player
Ubuntu
C言語
理想的な実行結果
[0] 入口==>(南)==>池==>(東)==>草原==>(北)==>森==>(南)==>草原==>(西)==>池==>(北)==
>入口==>(南)==>池==>(北)==>入口==>(東)==>森==>(東)==>湖==>(南)==>宝
[1] 入口==>(南)==>池==>(北)==>入口==>(南)==>池==>(東)==>草原==>(西)==>池==>(東)==
>草原==>(北)==>森==>(西)==>入口==>(東)==>森==>(西)==>入口==>(南)==>池==>(東)==>
草原==>(北)==>森==>(東)==>湖==>(南)==>宝
[2] 入口==>(東)==>森==>(東)==>湖==>(南)==>宝

[99] 入口==>(東)==>森==>(東)==>湖==>(南)==>宝

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • hige0119

    2017/08/01 09:21

    そもそも問題の意味が分からないのであれば穴埋めは無理かと思います。ここで質問をする前に問題の意味を理解するべきかと。

    キャンセル

  • 退会済みユーザー

    2017/08/02 16:38

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

  • 退会済みユーザー

    2017/08/05 17:26

    複数のユーザーから「意図的に内容が抹消された質問」という意見がありました
    解決後に編集機能を用いて質問内容を改変し関係のない内容にしたり、内容を削除する行為は禁止しています。
    投稿していただいた質問は、後に他の誰かが困ったときに助けになる情報資産になると考えるからです。
    「質問を編集する」ボタンから編集を行い、他のユーザにも質問内容が見えるように修正してください。

回答 1

checkベストアンサー

+6

強化学習に関しては素人ですが。。

  1. c言語の問題
  2. 強化学習の問題

と分けて考えることをおすすめします。

その1

void init_Q(double Qvalue[StateNum][ActNum])
{
int s,a;

/* すべての状態と行動の価値を0にする */

 ここは、c言語の問題です。
 「状態と行動の価値」を表す変数を0にしましょう。
  forループなどで実現できそうです。

/* この部分を自分で書く */

} 

その2

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)
    の価値は合計には含まない */
    /* この部分を自分で書く */

     これは、強化学習の問題です。
     env[state][a]の変数を判断しながら、「ルールの価値」を表す変数を合計します。
     ただし、「ボルツマン選択」をするということなので、その式に従います。
   (温度定数Tが低いほどエージェントは値の高いQ値を選択する可能性が上がり、
     逆にTが高いほどランダムに近い行動選択をするようになります。)
     このプログラムは試行回数が高くなるほど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;
        }
    }
} 

その3

void update_Q(double Qvalue[StateNum][ActNum], 
int p_state, int act, int state, int r)
{
   int a;
   double max; // 行動後の状態から取ることのできる行動の中での価値の最大値 

   この部分は、強化学習の問題です。
   強化学習で一番キモになる部分です。

   /* 取ることのできる行動に関する価値の中で最大値を求める */ 
   /* この部分を自分で書く */
   「取ることのできる行動に関する価値」を表す変数の中から最大値を求めます。
    forループで最大値を検索するのが良いかもしれません。
  ここでのポイントは、「行動後の状態」から検索することになります。

   /* 状態p_stateにおいて行動actをとることの価値を更新 */
   /* この部分を自分で書く */
  ここで、強化学習の方法のひとつの「Q学習」を使用します。
   Q学習の式は、下記になります。
   Q値(現在) = Q値(現在) + Alpha * (報酬 + Gamma * 最大値 - Q値(現在));

} 

こんな感じでしょうか。

強化学習は、AIブームで今流行っていますので、しっかり基本を勉強しておくと後で良いかもしれません。
(私も勉強中ですが。。)

プログラミングが苦手だと、c言語の問題と、強化学習の理論の2つを同時にこなす課題は大変だとは思いますが、まずはc言語をある程度覚えてから取り掛かったほうが良いかと思います。

勉強頑張ってください!

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/02 15:50

    ご助言ありがとうございます。もう少し考えて頑張ってみようと思っています。

    キャンセル

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

  • ただいまの回答率 87.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る