-以下のcollect.c, player.h, player.cを用意して、コンパイル・実行 --gcc -o game0 collect.c player.c bandit00.o --gcc -o game1 collect.c player.c bandit01.o --gcc -o game2 collect.c player.c bandit02.o --gcc -o game3 collect.c player.c bandit03.o --gcc -o game4 collect.c player.c bandit04.o --gcc -o game5 collect.c player.c bandit05.o --gcc -o game6 collect.c player.c bandit06.o --gcc -o game7 collect.c player.c bandit07.o --gcc -o game8 collect.c player.c bandit08.o --./game0 ---bandit00をプレイ --./gam1 ---bandit01をプレイ --./game2 ---bandit02をプレイ --./game3 ---bandit03をプレイ --./game4 ---bandit04をプレイ --./game5 ---bandit05をプレイ --./game6 ---bandit06をプレイ --./game7 ---bandit07をプレイ --./game8 ---bandit08をプレイ -collect.c #include <stdio.h> #include <stdlib.h> #include "bandit.h" #include "player.h" #define MAX_TRIAL 100000 int main(){ /* 変数定義・初期化 */ int i,j,select_arm=0; double reward=0.0,score[10000], max_score=0.0, tmp_score; for(i=0 ; i<10000 ; i++){ score[i]=0.0; } init_bandit(); /* バンディット初期化 */ init_player(); /* プレーヤー初期化 */ set_arm_num(get_arm_num()); /* バンディットの腕の数を取得 */ /* MAX_TRIAL回まで自動実行 */ /* 連続した10000回のうち最大のスコアを自動計算・更新 */ for(i=0 ; i<MAX_TRIAL ; i++){ /* 意思決定・それによるバンディットの実行*/ select_arm = decision_making(reward); reward = bandit(select_arm); if(reward < 0.0) reward = 0.0; /* 連続した10000回の最大スコアの確認 */ tmp_score=0.0; for(j=0 ; j<10000 ; j++) tmp_score += score[j]; if(tmp_score > max_score) max_score = tmp_score; /* 連続した10000回のスコアを更新 */ /* score[0] 〜score[9999] に対し, */ /* 最も古いものscore[9999]を消し, */ /* 一個ずつずらし(score[j] = score[j-1]) */ /* 最も新しいものをscore[0]に入れる */ for(j=9999 ; j> 0 ; j--) score[j] = score[j-1]; score[0] = reward; } printf("最大総獲得報酬: %lf\n", max_score); close_player(); return 0; } -player.h void init_player(); void close_player(); void set_arm_num(int arm_num); int decision_making(double previous_reward); -player.c --これを作成 #include "player.h" static int _arm_num=0; /* このファイルないでしか見えないグローバル変数 */ void init_player(){ return; } void close_player(){ return; } void set_arm_num(int arm_num){ if(arm_num>0){ _arm_num = arm_num; /* 使い方の例 */ } return; } int decision_making(double previous_reward){ /* _arm_numを使えます */ /* ここに、bandit00〜bandit08を”解く”プログラムを書く */ return 1; return _arm_num; // 最後の腕を選択する(腕3本のバンディットなら3番目の腕を選択する) } -分割コンパイルについて補足 #ref(DSC_0032.JPG,zoom,15%) -player.c --ヒント1:ファイルスコープ変数を使う ---ファイルスコープ変数とは(教科書・本・webも参考に) #ref(ファイルスコープ変数.png,zoom,70%) --ヒント2:decision_makingのprevious_rewardの説明 #ref(decision_making.png,zoom,70%) --ヒント3:bandit00用player #include "player.h" /* このファイルないでしか見えないグローバル変数 */ /* バンディットの腕の数 */ static int _arm_num=0; /* player(decision_making)が選択した腕番号 */ static int _player_select_arm; /* reward[i-1] がi番目の腕の報酬値.適当に超えない数字(20個の腕)にした */ /* 腕は1から,配列は0から始まるので,腕番号iとreward[ i-1 ]が対応 */ static double _reward[20]; void init_player(){ int i; _player_select_arm = -5; /* なんとなく,選択した腕がない状態を -5 としてみた */ for(i=0 ; i<20 ; i++){ _reward[i]=-5.0; /* なんとなく,値の入っていない状態を-5.0とする */ } return; } void close_player(){ return; } void set_arm_num(int arm_num){ if(arm_num>0){ _arm_num = arm_num; /* 使い方の例 */ } return; } int decision_making(double previous_reward){ /* _arm_numを使えます */ /* bandit00を”解く”プログラム */ int i; /* 前回選択した腕がいくつの報酬であったか記録 */ if( _player_select_arm != -5 ){ /* 1回目のプレイなど前回選択した腕がない(-5)状態か判定 */ /* 腕は1から,配列は0から始まるので,腕番号iとreward[ i-1 ]が対応 */ _reward[ _player_select_arm - 1 ] = previous_reward; } /* まずは試していない腕を試してみる */ for(i=1 ; i <= _arm_num ; i++){ if(_reward[i-1] == -5.0){ /* i番目の腕を試していない(rewardを持っていない,-5.0の状態) */ _player_select_arm = i; return i; } } /* 全部の腕を試していたら、その中から最も高い報酬の腕を選択 */ int max_reward=0; int max_arm=1; for(i=1 ; i <= _arm_num ; i++){ if( _reward[ i-1 ] >= max_reward ){ max_reward = _reward[ i-1 ]; max_arm = i; } } _player_select_arm = max_arm; return max_arm; } -player.c --ヒント4:bandit00用player ---ポインタの演習資料中の4.動的配列を用いて,腕の数ぴったりにreward[]を取得.ヒント3では,腕の数を十分な数(20個)にしていた. #include <stdlib.h> #include "player.h" /* このファイルないでしか見えないグローバル変数 */ /* バンディットの腕の数 */ static int _arm_num=0; /* player(decision_making)が選択した腕番号 */ static int _player_select_arm; /* reward[i-1] がi番目の腕の報酬値.*/ /* 腕は1から,配列は0から始まるので,腕番号iとreward[ i-1 ]が対応 */ static double* _reward; void init_player(){ _player_select_arm = -5; /* なんとなく,選択した腕がない状態を -5 としてみた */ return; } void close_player(){ /* 動的配列は free で解放する必要あり */ free( _reward ); return; } void set_arm_num(int arm_num){ int i; if(arm_num>0){ _arm_num = arm_num; /* 使い方の例 */ } /* ここでバンディットの腕の数が得られるので,rewardの初期化 */ /* reward[ 腕の数分の配列 ] を動的配列で確保 */ _reward = (double *)malloc(sizeof(double) * _arm_num); for(i=0 ; i < _arm_num ; i++){ _reward[i]=-5.0; /* なんとなく,値の入っていない状態を-5.0とする */ } return; } int decision_making(double previous_reward){ /* _arm_numを使えます */ /* bandit00を”解く”プログラム */ int i; /* 前回選択した腕がいくつの報酬であったか記録 */ if( _player_select_arm != -5 ){ /* 1回目のプレイなど前回選択した腕がない(-5)状態か判定 */ /* 腕は1から,配列は0から始まるので,腕番号iとreward[ i-1 ]が対応 */ _reward[ _player_select_arm - 1 ] = previous_reward; } /* まずは試していない腕を試してみる */ for(i=1 ; i <= _arm_num ; i++){ if(_reward[i-1] == -5.0){ /* i番目の腕を試していない(rewardを持っていない,-5.0の状態) */ _player_select_arm = i; return i; } } /* 全部の腕を試していたら、その中から最も高い報酬の腕を選択 */ int max_reward=0; int max_arm=1; for(i=1 ; i <= _arm_num ; i++){ if( _reward[ i-1 ] >= max_reward ){ max_reward = _reward[ i-1 ]; max_arm = i; } } _player_select_arm = max_arm; return max_arm; }