Bonjour, j'ai un Projet à réaliser mais pour cela il me faut un TP auquel je n'ai pas pu assister. Du coup j'ai essayé comme j'ai pu de me débrouiller mais ça me mets des messages d'erreurs : java.lang.NullPointerException .

Voila le sujet :
Dans ce TP, nous allons voir dans un exemple simple comment calculer la fonction de valeur vπ de façon exacte en inversant une matrice. Il faudra au préalable télécharger la librairie jama et l'inclure au projet eclipse.

Gridworld
Nous considérons les mondes de type Gridworld : le monde est représenté par une grille au sein de laquelle l'agent peut se déplacer (en haut/bas/gauche/droite) et certaines cases peuvent rapporter des récompenses ou éventuellement “téléporter” l'agent sur une autre case.

La classe Gridworld.java contient le squelette d'un programme à remplir. Le principe consiste à générer une grille avec des récompenses aléatoires, puis résoudre l'équation de Bellman afin de pouvoir améliorer la politique. Pour la classe il faut donc écrire les fonctions suivantes :

InitRdmPol()
qui initialise action, c.a.d. pour chaque point de la grille, initialise un ensemble d'actions (parmi les direction dir possibles), et associe une probabilité à cette action. On définira une politique action initiale aléatoire, par exemple une loi uniforme : une proba 0.2 pour chacune des 5 actions possibles.

HashMap<Integer,ArrayList<double[]>> computeTrans(String act)
Cette fonction calcule pi, les probabilités de Transition de s vers s′, partant de a: P(s′|s,a) (ces probabilités sont indépendantes de la politique). On a donc pour chaque état s (Integer) et chaque action act (String), une ArrayList qui liste tous les états accessibles depuis s, en prenant l'action a, ainsi que leur probabilité à chacun. Dans le cas présent, une action donnée mène en fait de façon certaine vers un unique état s′, donc la ArrayList ne contiendra qu'un élément (de type double[2]), dont la première composante est l'état, et la seconde composante est la probabilité d'y aboutir, qui est donc automatiquement 1.0 (toujours sachant s et a). L'intérêt principal de cette fonction dans le cas présent est donc la gestion des bords de la grille. On peut dans un premier temps envisager d'alléger le code en remplaçant ArrayList<double[]> par Integer. Remarque: la structure de pi est actuellement conçue telle qu'on accède au contenu avec pi.get(act).get(s).

double[] computeVecR()
Il s'agit de calculer le vecteur rπ. Pour chaque état s il faut calculer la récompense moyenne (c.a.d. pondérée par la politique p(a|s) et la matrice de transition π(s′|a,s))

double[][] computeMatP()
Calcule la matrice Pπ

Une fois ces fonctions écrites le programme devrait calculer la fonction de valeur V pour la politique initialement définie. Finalement il faudra ensuite écrire la fonction suivante :

void ImprovePolicy(double[][] V)
Permet d'améliorer de façon gloutonne la politique en se basant sur le calcul de V. (il faudra itérer plusieurs fois pour atteindre une politique d'action satisfaisante).
Et voila ce que j'ai avec les codes des autres fonctions:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
package bellman;
 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import Jama.*;
 
public class GridWorld_sql {
 
	private boolean[][] grid;
	private double[][] reward;
	private int size_x;
	private int size_y;
	private int nbStates;
	private double gamma = 0.5;
	private Random rdmnum;
	private long seed = 124;
	private int MAX_REWARD = 20;
	private HashMap<Integer,HashMap<String,Double>> action;
	private HashMap<Integer, Integer> Rappel;
	private HashMap<Integer, Integer> Rappel2;
	private HashMap<String,HashMap<Integer,ArrayList<double[]>>> pi;
	private ArrayList<String> dir;
 
	GridWorld_sql(int size_x, int size_y, int n_rew) {
		this.rdmnum = new Random(this.seed);
 
		this.grid = new boolean[size_x][size_y];
		this.reward = new double[size_x][size_y];
		this.size_x = size_x;
		this.size_y = size_y;
		this.nbStates = size_x*size_y;
 
		// list of actions
		this.dir = new ArrayList<String>();
		this.dir.add("left");
		this.dir.add("up");
		this.dir.add("right");
		this.dir.add("down");
		this.dir.add("stay");
 
		for(int i=0; i<size_x; i++) {
			for(int j=0; j<size_y; j++)
				grid[i][j] = false;
		}
 
		//this.ChooseRdmState();
		// put n_rew reward randomly
		this.PutRdmReward(n_rew);
		// initialize the random policy
		this.InitRdmPol();
		// initialize the transition matrices
		this.InitTransitionMat();
	}
 
	// choose a random coordinate in the grid
	private void ChooseRdmState() {
		int i = rdmnum.nextInt(size_x);
		int j = rdmnum.nextInt(size_y);
		grid[i][j] = true;
	}
 
	// add a reward randomly on the grid
	private void PutRdmReward(int n_rew) {
		int n = 0;
		while(n<n_rew) {
			int i = rdmnum.nextInt(size_x);
			int j = rdmnum.nextInt(size_y);
			if(reward[i][j] == 0) {
				reward[i][j] = rdmnum.nextInt(MAX_REWARD);
				n++;
			}
		}
	}
 
	// return a state given a coordinate on the grid
	private int GridToState(int i, int j) {
		return (i+1)+size_x*(j+1);
	}
 
	// return the coordinate on the grid given the state
	private int[] StateToGrid(int s) {
		int[] index = new int[2];
		index[1] = (int) s/size_x;
		index[0] = s-index[1]*size_x;
		return index;
	}
 
	// add the possible actions for all states
	private void InitRdmPol() {
		action = new HashMap<Integer,HashMap<String,Double>>();
		HashMap<String,Double> mapinter = new HashMap<String,Double>();
 
		HashMap<String,Integer> casesPossibles = new HashMap<String, Integer>();
		double Prob = 0;
		int count = 0;
 
		this.Rappel = new HashMap<Integer, Integer>();
		this.Rappel2 = new HashMap<Integer, Integer>();
 
		for(int i=0; i<size_x; i++) {
			for(int j=0; j<size_y; j++) {
				count++;
				int a = 0;
				if(i-1 < 0) {
					casesPossibles.put(dir.get(0),1);
				} else { 
					casesPossibles.put(dir.get(0),0);
				}
 
				if(i+1 >= size_x) {
					casesPossibles.put(dir.get(2),1);
				} else { 
					casesPossibles.put(dir.get(2),0);
				}
 
				if(j-1 < 0) {
					casesPossibles.put(dir.get(3),1);
				} else { 
					casesPossibles.put(dir.get(3),0);
				}
 
				if(j+1 >= size_y) {
					casesPossibles.put(dir.get(1),1);
				} else { 
					casesPossibles.put(dir.get(1),0);
				}
 
				casesPossibles.put(dir.get(4),1);
 
				for(String m : casesPossibles.keySet()) {
					if(casesPossibles.get(m) == 1) {
						a++;
					}
				}
 
				Prob = 1/a;
 
				for(int k=0; k<dir.size(); k++) {
					mapinter.put(dir.get(k), Prob);
				}
				this.action.put(count, mapinter);
				this.Rappel.put(count, GridToState(i,j));
				this.Rappel2.put(GridToState(i,j),count);
				mapinter.clear();
				casesPossibles.clear();
			}
		}
	}
 
 
	// return the direction (on the grid) for a given action
	private int[] getDirNeighbor(String act) {
		int[] d = new int[2];
 
		if(act.equals("left")) d[0]=-1;
		if(act.equals("right")) d[0]=1;
		if(act.equals("up")) d[1]=1;
		if(act.equals("down")) d[1]=-1;
 
		return d;
	}
 
	// To each state, give the reachable states given an action
	private HashMap<Integer,ArrayList<double[]>> computeTrans(String act) {
		HashMap<Integer,ArrayList<double[]>> trans = new HashMap<Integer,ArrayList<double[]>>();
		int[] d = getDirNeighbor(act);
 
		for(int i=0; i<size_x; i++) {
			for(int j=0; j<size_y; j++) {
				ArrayList<double[]> p = new ArrayList<double[]>();
				double[] q = new double[2];
 
				if(i+d[0] < 0 || i+d[0] >= size_x || j+d[1] < 0 || j+d[1] >= size_y) {
					q[0] = GridToState(i+d[0], j+d[1]);
					q[1] = 0;
					p.add(q);
				} else {
					q[0] = GridToState(i+d[0], j+d[1]);
					q[1] = 1.0;
					p.add(q);
				}
 
				trans.put(GridToState(i,j), p); 
			}
		}
		return trans;
	}
 
	// initiate values of P
	private void InitTransitionMat() {
		pi = new HashMap<String,HashMap<Integer,ArrayList<double[]>>>();
		for(String act : this.dir) {
			pi.put(act,computeTrans(act));
		}
	}
 
	// compute the vector r
	private double[] computeVecR() {
		double[] R = new double[nbStates];
		for(int s=0; s<nbStates; s++) {
			double sum = 0;
			HashMap<String,Double> a = action.get(s);
			int c= Rappel.get(s);
 
			int[] coord = StateToGrid(c);
 
			// compute the reward obtained from state s, by doing all potential action a
			for(String act : this.dir) {
				ArrayList<double[]> d = pi.get(act).get(c);
				double[] doub = d.get(0);
				double e = doub[1];
 
				sum += a.get(act) * e * reward[coord[0]][coord[1]];
			}
			R[s] = sum;
		}
		return R;
	}
 
	private double[][] computeMatP() {
		double[][] P = new double[nbStates][nbStates];
 
		for(int s=0; s<nbStates; s++) {
			int state = Rappel.get(s);
			// from state s, compute P^{\pi}(s,s')
			for(String act : this.dir) {
				int[] coord = StateToGrid(state);
				int[] d = getDirNeighbor(act);
				coord[0] = coord[0]+ d[0];
				coord[1] = coord[1]+ d[1];
				int newstate = GridToState(coord[0], coord[1]);
				int s2 = Rappel2.get(newstate);
				P[s][s2] = action.get(s).get(act) * pi.get(act).get(state).get(0)[1];
			}
		}
		return P;
	}
 
	// converting to matrix for the inverse
	private Matrix BuildMatA() {
		double[][] f_A = new double[nbStates][nbStates];
		double[][] P = computeMatP();
		for(int s=0; s<nbStates; s++) {
			f_A[s][s] = 1;
			for(int sp=0; sp<nbStates; sp++) {
				f_A[s][sp] -= this.gamma*P[s][sp];
			}
		}
 
		Matrix matP = new Matrix(f_A);
		return new Matrix(f_A);
	}
 
	// converting to matrix for the inverse
	private Matrix BuildMatb() {
		double[] vec_b = computeVecR();
		double[][] b = new double[vec_b.length][1];
		for(int i=0; i<vec_b.length; i++) {
			b[i][0] = vec_b[i];
		}
		return new Matrix(b);
	}
 
	// solving the linear system
	private double[][] SolvingP() {
		Matrix x = BuildMatA().solve(BuildMatb());
		return x.getArray();
	}
 
	private void showGrid() {
		for(int i=0; i<size_x; i++) {
			for(int j=0; j<size_y; j++)
				System.out.print((this.grid[i][j]?1:0));
			System.out.println();
		}
	}
 
	private void showRewGrid() {
		for(int i=0; i<size_x; i++) {
			for(int j=0; j<size_y; j++)
				System.out.print(this.reward[i][j]+" ");
			System.out.println();
		}
	}
 
	// improve the policy by looking at the best_a Q(s,a)
	private void ImprovePolicy(double[][] V) {
		action = new HashMap<Integer,HashMap<String,Double>>();
		for(int i=0; i<size_x; i++) {
			for(int j=0; j<size_y; j++) {
				// TODO
			}
		}			
	}
 
	public static void main(String[] args) {
		GridWorld_sql gd = new GridWorld_sql(5,5,2);
 
		gd.showRewGrid();
		double[][] V = gd.SolvingP();
		// show V
		for(int i=0; i<gd.nbStates; i++) {
			if(i%5==0) System.out.println();
			System.out.print(V[i][0]+" ");			
		}
		System.out.println("\n");
		// Improve the policy !
		gd.ImprovePolicy(V);
 
	}
}

Comme vous pouvez le voir, j'ai réaliser la majorité des fonctions sauf la dernière demandée car j'ai des messages d'erreurs.
Je voudrais dans un premier temps savoir si ce que j'ai fais est bon (parce que je sais pas si c'est bien ce qu'ils demandent), comment corriger les erreurs et pourquoi elles sont là et aussi de l'aide pour la dernière question.
Merci d'avance, et Bonne Année!