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<doub le[]>> 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: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!
-----