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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

3回答

1657閲覧

乱数を使った強化学習の実行結果が大幅に変わることはおかしくないか.

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2018/12/06 01:19

前提・実現したいこと

NNのグリッドワールドの任意の位置にゴールを配置する.(これは一回だけです)
N
Nのグリッドワールドの任意の位置にエージェントを配置する.(これは繰り返し回数loop回です)
1番始めは, 任意のマスの上下左右は等確率で移動するようにするが,
移動の上限回数以内にゴールした場合は,ゴールから一定のステップだけ遡って
報酬を与える.(このときゴールから遠ざかるほど報酬は小さくなる.)
つまり,あるマスのある方向が,ゴールしたときに通られれば通られるほどその方向は確率が
大きくなる.(注意)繰り返し回数が終わるまで確率は更新しつづけるので上下左右を等確率で
設定するのは実行時の最初の1回だけです.)
(また繰り返し回数分エージェントは作り, それぞれのスタート位置も異なります.)
これを繰り返し回数だけやったのちに,(後半戦突入)再び繰り返し回数だけ任意の位置にエージェントを配置して
ゴールを目指すが,このときの移動は確率に基づくのでは無く,前半で設定した確率のうち一番
大きいものを移動方向として採用する.また,ゴールの位置は1行目で配置した位置と同じ位置である.
このときゴールした回数を求める.

といったことをしたいです.
拙い日本語で申し訳ありません.

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

エラーメッセージは出ておりません. 同じnについて、ゴールの回数が実行ごとに大幅に変わってしまうことに違和感があって, 僕のコードがおかしいと思うので指摘していただきたいです. 乱数を使っているので実行結果が変わること自体は感覚的に納得しますが たとえば, n=5のときに実行結果が下は0から上は66まで出るのはさすがに変だと思います. また, 報酬を与える際のやり方もうまいやり方がわかりません.(GridクラスのsetArrowメソッド) (確率なので合計だけでなく各方向も0以上1以下に収めるべきかなと思うのですが、 例えば0.01, 0.01, 0.01, 0.97から報酬を0.97をもつ方向に0.5あげると0.97が 1を超えて0.01は0を下回りますが, 0.97を1で押さえつけてしまうと正しい評価にならないんじゃ ないかとも思います.)

該当のソースコード

java

1/////Main.javaです///// 2import java.util.*; 3 4public class Main{ 5 public static void main(String[] args){ 6//原則入力を受け付けますが,入力の手間を省くためここでは予め値を代入しています 7 8 /*Scanner sc = new Scanner(System.in); 9 System.out.print("マップの大きさ:"); 10 int n = sc.nextInt(); 11 System.out.print("ステップ数:"); 12 int T = sc.nextInt(); 13 System.out.print("繰り返し回数:"); 14 int loop = sc.nextInt(); 15 System.out.print("報酬:"); 16 double P = sc.nextDouble(); 17 System.out.print("エージェントの寿命:"); 18 int life = sc.nextInt(); 19 int tactics = 0; 20 int cnt = 0;*/ 21//各変数の値は適当です. 22 int n = 5;//グリッドワールドの大きさ, ここでは25(5*5)マスあることになります. 23 int T = 50;//ゴールして報酬を与える際, ゴールから遡るステップ数です. 24 int loop = 100;//繰り返し回数です. 25 double P = 0.5;//ゴールした際に与える報酬です. 26 int life = 200;//1つのエージェントがゴールを目指すときに動ける上限回数です. 27 int tactics = 0;//ゴールした際に報酬を与えるかカウントするかの違いのために使います. 28 //(続き)tactics == 2 のときは<前提・実現したいこと>の(後半戦)に当たります. 29 int cnt = 0;//後半戦におけるゴールへの到達回数です. 30 31 Agent.setVariable(n, T, life, P); 32 Agent.setGoal(); 33 Grid grid = new Grid(n); 34 35 for(tactics = 1; tactics <= 2; tactics++){ 36 for(int i = 0; i < loop; i++){ 37 boolean ans = true; 38 Agent agent = new Agent(); 39 40 for(int j = 0; j < life; j++){ 41 //ans==1のときはゴールしたときです. 42 ans = agent.askDirectory(grid, j, tactics); 43 if(ans){ 44 if(tactics == 1){ 45 //報酬を与えます. 46 agent.giveReward(grid, j); 47 } 48 //到達回数を数えます. 49 if(tactics == 2) cnt++; 50 break; 51 } 52 } 53 } 54 } 55 System.out.println(cnt); 56 } 57} 58 59/////Agent.javaです///// 60import java.util.*; 61 62public class Agent{ 63 private final int UP = 0; 64 private final int RIGHT = 1; 65 private final int DOWN = 2; 66 private final int LEFT = 3; 67 68 private int[] history;//移動方向を保存する配列 69 private int[][] start = new int[1][2]; 70 private int[][] tmp = new int[1][2]; 71 private static int[][] goal = new int[1][2]; 72 private static int n; 73 private static int T; 74 private static int life; 75 private static double P; 76 77//エージェントごとに(繰り返し回数の1回1回で)スタート位置は異なります. 78 public Agent(){ 79 Random r = new Random(); 80 history = new int[Agent.life];//移動の上限回数分用意します. 81 this.start[0][0] = this.tmp[0][0] = r.nextInt(Agent.n); 82 this.start[0][1] = this.tmp[0][1] = r.nextInt(Agent.n); 83 //System.out.println("start_x:" + this.start[0][0]); 84 //System.out.println("start_y:" + this.start[0][1]); 85 } 86 87 public static void setVariable(int n, int T, int life, double P){ 88 Agent.n = n; 89 Agent.T = T; 90 Agent.life = life; 91 Agent.P = P; 92 } 93 94//ゴールの位置は, 1回の実行においてすべてのエージェントに共通なのでクラス変数にします. 95 public static void setGoal(){ 96 Random r = new Random(); 97 Agent.goal[0][0] = r.nextInt(Agent.n); 98 Agent.goal[0][1] = r.nextInt(Agent.n); 99 } 100 101 public boolean askDirectory(Grid g, int life, int tactics){ 102 boolean flag = false; 103 104//移動先がグリッドワールド以内であるとおきwhile文を抜けます. 105 while(flag == false){ 106 int next_line = this.tmp[0][0]; 107 int next_row = this.tmp[0][1]; 108 int d = 0; 109//移動方向を決めるときに, 確率的なのがtactics==1, 確率が一番大きい方向を使うのがelse(tactics==2)です. 110 if(tactics == 1){ 111 d = g.showDirectoryLearn(this.tmp[0][0], this.tmp[0][1]); 112 }else{ 113 d = g.showDirectoryAssess(this.tmp[0][0], this.tmp[0][1]); 114 } 115 116 switch(d){ 117 case UP: 118 next_line--; 119 break; 120 case RIGHT: 121 next_row++; 122 break; 123 case DOWN: 124 next_line++; 125 break; 126 case LEFT: 127 next_row--; 128 break; 129 } 130 131 if(0<=next_line && next_line<Agent.n && 0<=next_row && next_row<Agent.n ){ 132 this.tmp[0][0] = next_line; 133 this.tmp[0][1] = next_row; 134 history[life] = d; 135 flag = true; 136 } 137 } 138 139 if(this.tmp[0][0] == Agent.goal[0][0] && this.tmp[0][1] == Agent.goal[0][1]){ 140 return true; 141 }else{ 142 return false; 143 } 144 145 } 146 147 public void giveReward(Grid grid, int j){ 148 int d = 0; 149 double reward = 0; 150 int next_line = Agent.goal[0][0]; 151 int next_row = Agent.goal[0][1]; 152 153 int target = 0; 154 int idx = j; 155 int t = 1; 156 157//例えば1ステップ目でゴールしたとき, j=0. ということは1ステップ目の方向はhistory[0]に入っている. 158//tは遡った回数です. Tステップだけ遡り, かつ添字は0以上のときだけ報酬を考える. 159 while(idx >= 0 && t <= Agent.T){ 160 d = history[idx]; 161 162 switch(d){ 163 case UP: 164 next_line++; 165 break; 166 case RIGHT: 167 next_row--; 168 break; 169 case DOWN: 170 next_line--; 171 break; 172 case LEFT: 173 next_row++; 174 break; 175 } 176 177 if(next_line == 0){ 178 target = next_row; 179 }else{ 180 target = next_line * Agent.n + next_row; 181 } 182//報酬の式は[ゴールからtステップ遡るグリッドにおいて行動d(dは上下左右のどれかを表します) 183//を選択したとき, d^tとして, 確率をlength_old(d^t)を次の式によりlength_new(d^t)に変更します. 184//length_new(d^t) = length_old(d^t) + P * (T - t + 1)/T (t = 1, 2, ・・・, T]です. 185//ここでは, +の後ろを計算してrewardに入れて, それをsetArrowを使ってグリッドに設定しに行きます. 186 reward = this.P * (Agent.T - t + 1) / Agent.T; 187 188 grid.setArrow(target, d, reward); 189 190 idx--; 191 t++; 192 } 193 } 194 195} 196 197/////Grid.javaです///// 198import java.util.*; 199 200public class Grid{ 201 private final int UP = 0; 202 private final int RIGHT = 1; 203 private final int DOWN = 2; 204 private final int LEFT = 3; 205 206 private int[][] map; 207 private double[][] arrow; 208 private int n; 209 210 private List<Integer> arylist = new ArrayList<>(); 211 212 213 public Grid(int n){ 214 this.n = n; 215 this.map = new int[n][n];//いらないっぽいです. 216 this.arrow = new double[n*n][4];//すべてのマスの上下左右4方向の確率を入れるための配列 217 setArrowEqual(n); 218 } 219 220//実行時一番はじめに4方向の確率を等しくします. 221 public void setArrowEqual(int n){ 222 for(int i = 0; i < n*n; i++){ 223 for(int j = 0; j < 4; j++){ 224 this.arrow[i][j] = 0.25; 225 } 226 } 227 } 228 229 public int showDirectoryLearn(int line, int row){ 230 int target = 0; 231//エージェントのx座標(line), y座標(row)に対応するarrowの添字を見つけます. 232//1行n列(map[0][n-1])に対応するのはarrow[n-1], 2行n列(map[1][2n-1])に対応するのはarrow[2n-1] 233//なので, これを一般化したものです. 234 if(line == 0){ 235 target = row; 236 }else{ 237 target = line * this.n + row; 238 } 239 240//最初は等確率なので, やってることは0.25以下は上, 0.50以下は右という風な設定です. 241 double up = this.arrow[target][0]; 242 double right = up + this.arrow[target][1]; 243 double down = right + this.arrow[target][2]; 244 double left = down + this.arrow[target][3]; 245 246 Random r = new Random(); 247 double value = r.nextDouble(); 248 if(value <= up){return UP;} 249 if(value <= right){return RIGHT;} 250 if(value <= down){return DOWN;} 251 return LEFT; 252 } 253 254//tactics==2のときは確率が一番大きいものを選びます. 255//ただし複数の方向が最大値をもつときはそれらの中からランダムに方向を選びます. 256 public int showDirectoryAssess(int line, int row){ 257 int target = 0; 258 int cnt = 0; 259 double max = Double.MIN_VALUE; 260 int ans = 0; 261 262 if(line == 0){ 263 target = row; 264 }else{ 265 target = line * this.n + row; 266 } 267//最大値を求めます. 268 for(int i = 0; i < 4; i++){ 269 max = Math.max(this.arrow[target][i], max); 270 } 271//最大値をもつ個数を知ります. 272 for(int i = 0; i < 4; i++){ 273 if(max == this.arrow[target][i]) this.arylist.add(i); 274 } 275 276 if(this.arylist.size() == 1){ 277 ans = this.arylist.get(0); 278 }else{ 279 Random r = new Random(); 280 int value = r.nextInt(this.arylist.size()); 281 ans = this.arylist.get(value); 282 } 283 284 this.arylist.clear(); 285 return ans; 286 } 287//このやり方では, 合計確率は1ですが, ある方向が1を超えたり0を下回る可能性があり, 288//うまいやり方が見つかりません. 289 public void setArrow(int target, int d, double reward){ 290 for(int i = 0; i < 4; i++){ 291 this.arrow[target][i] -= reward / 3; 292 } 293 this.arrow[target][d] += 4 * reward / 3; 294 } 295} 296

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

java version "10.0.2" 2018-07-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)

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

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

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

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

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

guest

回答3

0

本プログラムの結果を左右する原因にはなりません(※)が、1つだけ指摘しておきます。

コードでは乱数を必要とする場面でその都度乱数発生器を初期化している個所があります。

計算機における乱数の発生はあるseed値から始めてなんらかの演算(seed値に対してbitをかき混ぜるような演算)を施し次々に数値を生成(それを疑似的な乱数とみなす)という方法を用います。seed値が同じ値の場合は発生する乱数はまったく同一のものになります。
本来は「一連の乱数が必要となるような論理でただ1回だけ初期化された乱数発生器をずっと使い続ける」のが普通です。

一番望ましい方法は同一のスレッド内で用いる乱数発生器はただ一つにすることだと思います。

java

1// よい例: 2 3class Main { 4 static Random random = new Random(); 5 6 ... 7 8 void foo(Other other) { 9 // Javaバージョンにかかわらず結果がtrueになる確率は概ね10% 10 System.out.println(random.nextInt(10) == other.bar(10)); 11 } 12} 13 14class Other { 15 int bar(int n) { 16 return Main.random.nextInt(n); 17 } 18} 19 20// 悪い例 21 22class Main { 23 int foo(Other other) { 24 // メソッドが呼び出されるたびに必要となる乱数を、毎回生成した乱数発生器により求めるのはおかしい 25 Random random = new Random(); 26 int randomNumber = random.nextInt(10); 27 // randomNumberにより何か計算する 28 return result; 29 } 30}

※:
Java 10.0.2時点ではRandomクラスの引数なしコンストラクターでのseed値は「いかなるスレッドからいかなるタイミングで並行して呼び出されても、各々がなるべくユニークなseed値を持つような配慮」が施されています。それゆえ乱数が必要な場面で毎回乱数発生器を生成してもそこそこランダムな値となるようになっています。

しかし例えばJava 8のRandom()は単にSystem.currentTimeMillis()をseed値にしていたため、乱数発生器を「異なるクラスごとに準備」するような論理を用いてしまうとそれぞれのクラス上にある乱数発生器のseed値が同一の値で初期化される確率が非常に高くなります。もしseed値が同一だと生成される乱数列はまったく同一のものになります。

それを防ぐためには

  • 同一のスレッドではただ一つの乱数発生器を用いる
  • 乱数発生器を生成する際に自前でなるべくユニークな値となるようなseed値を用いるように工夫する

といった配慮が必要でした。java10ではそのような工夫が必要なくなり、複数の個所で乱数発生器が必要な場面でも引数なしコンストラクターRandom()でよくなりちょっと使いやすくなりました。逆に言えばそういう場面の使い勝手がよくなっただけにすぎず、乱数発生器の使い方の基本は依然として「必要な乱数列を得るためにただ一つの乱数生成器を用いるべき」であることには変わりはありません。

投稿2018/12/06 04:40

KSwordOfHaste

総合スコア18394

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

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

退会済みユーザー

退会済みユーザー

2018/12/06 05:28

回答ありがとうございます. そういう作法というか, きちんとした乱数の使い方を知りませんでした. Main.javaで Random r = new Random(); をして, このrを各クラスファイルのメンバ変数に設定しなおしました. 今更気づいたのですが, Random()を使うことで実行時の時刻に乱数列が左右されるので 毎回cntの値が変わることは当たり前かなと思い, seedを自分で指定してみました. (例えば, long seed = 20; Random r = new Random(seed);のようにです) このとき, seedの値によって, nとの相関が取れたり取れなかったりして(これも 当たり前っちゃ当たり前ですが...)nと回数の関係がseedに左右されるのはおかしな 話だと思うのですが, どう思われますか...?
KSwordOfHaste

2018/12/09 02:37

コメント遅くなりましたが・・・ 自分が回答したために混乱させてしまったなら申し訳ないのですが、自分の指摘は先頭に書いたように、「本プログラムの結果を左右する原因にはならない」ものであり乱数の発生のさせかたが普通ではないので「それはそれで直しておいた方が今後のためによいと思う」といった程度のことでしかありません。 自己解決されたようで何よりですが、解決したということは原因はswordoneさんが指摘しておられる「確率の扱いの問題」だったのだと思います。おそらく乱数生成の部分は自分の指摘を反映しようがしまいが結果には大きな違いは出ないと思います。
guest

0

「報酬」とやらを、確率の値として加減しているのが変に思います。
ただ単にスコアとして加算記録し、そのスコアの合計の大小で方向を決定するというのはどうでしょう。
例えばゴールから10ステップ前に戻った場所での選択方向に50-10=40ポイント加算し、
ある地点での上下左右の方向のそれぞれのスコアが50,100,150,200とかなら、一番大きい右に移動する、といった具合に。

関係ないですが、配列の使い方が変です。
Agentのgoalとかtmpとかstartをnew int[1][2]で生成していますが、最初の[1]が無駄です。
またGridで2次元にし、グリッドの位置を1次元変換していますが、それなら3次元使ったほうがわかりやすいです。
1次元変換するにしても、lineが0か否かで場合分けするのが無駄です。0でも同様の計算ができますから。

投稿2018/12/06 03:02

swordone

総合スコア20651

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

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

退会済みユーザー

退会済みユーザー

2018/12/06 04:11

いつも回答ありがとうございます. 報酬の与え方について, 加減から加算のみに変えてみました。 ご指摘いただいて変更を加えたところは 変数については ・goal, tmp, startを[1][2]から[2]へ ・arrowを[n*n][4]から[n][n][4]へ メソッドについては ・GridクラスのsetArrowメソッドを public void setArrow(int line, int row, int d, double reward){ this.arrow[line][row][d] += reward; } ・GridクラスのshowDirectoryLearnメソッドを public int showDirectoryLearn(int line, int row){ double sum = 0; for(int i = 0; i < 4; i++){sum += this.arrow[line][row][i];} double up = this.arrow[line][row][0]; double right = up + this.arrow[line][row][1]; double down = right + this.arrow[line][row][2]; double left = down + this.arrow[line][row][3]; Random r = new Random(); double value = r.nextDouble() * sum; if(value <= up){return UP;} if(value <= right){return RIGHT;} if(value <= down){return DOWN;} return LEFT; } です. ただ, こうした場合であってもcntが実行ごとに大きくばらついてしまうのですが, そういうものなのでしょうか?
guest

0

ベストアンサー

##問題
実行毎に結果が「大きく」異なる
##原因
Randomクラスの引数なしコンストラクタRandom()は現在時刻を利用するため
実行毎に得られる乱数列が異なる
##考えた解決法
0. seed値を指定して乱数列を得れば,実行毎すべてで等しい結果が得られる -> x
(理由) どのseed値であればうまい結果が得られるのか分からない

  1. Random()クラスのRandom()を使うが, 以前のただの100回繰り返しではなく

100回繰り返しを複数回行って平均をとることで, 実行時刻による結果の差異を減らす -> o
(理由) 同じグリッドワールドの結果の差異に以前のような大きな開きがなく, グリッドワールドの
サイズが大きくなるとゴール回数も減る(のでおそらくこれでいいかなと)
##プログラムの変更点

  • 繰り返し100回を行い, それを結果とした -> 繰り返し100回を100回行い, その平均を結果とすることにした

KSwordOfHasteさんのコメントより

  • 乱数を使うたびに乱数生成器を作っていた -> Main.javaの序盤1回だけにした

swordoneさんのコメントにより

  • goal, tmp, startが二次元配列だった -> 一次元配列にした
  • arrowが二次元配列だった -> 三次元配列にした
  • 報酬の与え方について, ゴールするときに通った方向はプラスの報酬,

通らなかった方向はマイナスの報酬だった -> 通った方向にプラスの報酬のみにした(追記1)

java

1Main.javaです///////////////////////////////////////////////////////////////////// 2 3import java.util.*; 4 5public class Main{ 6 public static void main(String[] args){ 7 int n = 5; 8 int T = 5; 9 int loop = 100; 10 int cntAverage = 100; 11 double P = 10; 12 int life = 10; 13 int level = 0; 14 int cntAssess = 0; 15 int[] goal = {0, 0}; 16 Random r = new Random(); 17 18 Agent.setVariable(n, T, life, P, r, goal); 19 Grid grid = new Grid(n, r); 20 21 for(level = 1; level <= 2; level++){ 22 for(int i = 0; i < cntAverage; i++){ 23 for(int j = 0; j < loop; j++){ 24 boolean ans = true; 25 Agent agent = new Agent(); 26 for(int k = 0; k < life; k++){ 27 ans = agent.askDirectory(grid, k, level); 28 if(ans){ 29 agent.giveReward(grid, k); 30 if(level == 1){break;} 31 if(level == 2){cntAssess++; break;} 32 } 33 } 34 } 35 } 36 } 37 38 System.out.println("cntAssess average:" + cntAssess / cntAverage); 39 } 40} 41 42Grid.javaです/////////////////////////////////////////////////////////////// 43 44import java.util.*; 45 46public class Grid{ 47 private final int UP = 0; 48 private final int RIGHT = 1; 49 private final int DOWN = 2; 50 private final int LEFT = 3; 51 private int[][] map; 52 private double[][][] arrow; 53 private int n; 54 Random r; 55 private List<Integer> arylist = new ArrayList<>(); 56 57 public Grid(int n, Random r){ 58 this.n = n; 59 this.map = new int[n][n]; 60 this.arrow = new double[n][n][4]; 61 this.r = r; 62 setArrowEqual(n); 63 } 64 65 public void setArrowEqual(int n){ 66 for(int i = 0; i < n; i++){ 67 for(int j = 0; j < n; j++){ 68 for(int k = 0; k < 4; k++){ 69 this.arrow[i][j][k] = 0.25; 70 } 71 } 72 } 73 } 74 75 76 public int showDirectoryLearn(int line, int row){ 77 double sum = 0; 78 for(int i = 0; i < 4; i++){sum += this.arrow[line][row][i];} 79 80 double up = this.arrow[line][row][0]; 81 double right = up + this.arrow[line][row][1]; 82 double down = right + this.arrow[line][row][2]; 83 double left = down + this.arrow[line][row][3]; 84 double value = this.r.nextDouble() * sum; 85 86 if(value <= up){return UP;} 87 if(value <= right){return RIGHT;} 88 if(value <= down){return DOWN;} 89 return LEFT; 90 } 91 92 93 public int showDirectoryAssess(int line, int row){ 94 int cnt = 0; 95 double max = Double.MIN_VALUE; 96 int ans = 0; 97 98 for(int i = 0; i < 4; i++){ 99 max = Math.max(this.arrow[line][row][i], max); 100 } 101 102 for(int i = 0; i < 4; i++){ 103 if(max == this.arrow[line][row][i]) this.arylist.add(i); 104 } 105 106 if(this.arylist.size() == 1){ 107 ans = this.arylist.get(0); 108 }else{ 109 int value = this.r.nextInt(this.arylist.size()); 110 ans = this.arylist.get(value); 111 } 112 113 this.arylist.clear(); 114 return ans; 115 } 116 117 public void setArrow(int line, int row, int d, double reward){ 118 this.arrow[line][row][d] += reward; 119 } 120} 121 122Agent.javaです//////////////////////////////////////////////////////////////////// 123 124 125import java.util.*; 126 127public class Agent{ 128 private final int UP = 0; 129 private final int RIGHT = 1; 130 private final int DOWN = 2; 131 private final int LEFT = 3; 132 private int[] history; 133 private int[] start = new int[2]; 134 private int[] tmp = new int[2]; 135 private static int[] goal = new int[2]; 136 private static int n; 137 private static int T; 138 private static int life; 139 private static double P; 140 private static Random r; 141 142 public Agent(){ 143 history = new int[Agent.life]; 144 this.start[0] = this.tmp[0] = Agent.r.nextInt(Agent.n); 145 this.start[1] = this.tmp[1] = Agent.r.nextInt(Agent.n); 146 } 147 148 public static void setVariable(int n, int T, int life, double P, Random r, int[] goal){ 149 Agent.n = n; 150 Agent.T = T; 151 Agent.life = life; 152 Agent.P = P; 153 Agent.r = r; 154 Agent.goal[0] = goal[0]; 155 Agent.goal[1] = goal[1]; 156 } 157 158 public boolean askDirectory(Grid g, int life, int level){ 159 boolean flag = false; 160 161 while(flag == false){ 162 int next_line = this.tmp[0]; 163 int next_row = this.tmp[1]; 164 int d = 0; 165 if(level == 1){ 166 d = g.showDirectoryLearn(this.tmp[0], this.tmp[1]); 167 }else{ 168 d = g.showDirectoryAssess(this.tmp[0], this.tmp[1]); 169 } 170 171 switch(d){ 172 case UP: 173 next_line--; 174 break; 175 case RIGHT: 176 next_row++; 177 break; 178 case DOWN: 179 next_line++; 180 break; 181 case LEFT: 182 next_row--; 183 break; 184 } 185 186 if(0<=next_line && next_line<Agent.n && 0<=next_row && next_row<Agent.n ){ 187 this.tmp[0] = next_line; 188 this.tmp[1] = next_row; 189 history[life] = d; 190 flag = true; 191 } 192 } 193 194 if(this.tmp[0] == Agent.goal[0] && this.tmp[1] == Agent.goal[1]){ 195 return true; 196 }else{ 197 return false; 198 } 199 } 200 201 public void giveReward(Grid grid, int j){ 202 int d = 0; 203 double reward = 0; 204 int next_line = Agent.goal[0]; 205 int next_row = Agent.goal[1]; 206 int idx = j; 207 int t = 1; 208 209 while(idx >= 0 && t <= Agent.T){ 210 d = history[idx]; 211 switch(d){ 212 case UP: 213 next_line++; 214 break; 215 case RIGHT: 216 next_row--; 217 break; 218 case DOWN: 219 next_line--; 220 break; 221 case LEFT: 222 next_row++; 223 break; 224 } 225 226 reward = this.P * (Agent.T - t + 1) / Agent.T; 227 grid.setArrow(next_line, next_row, d, reward); 228 idx--; 229 t++; 230 } 231 } 232} 233

投稿2018/12/09 02:01

編集2018/12/09 02:04
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問