2016-11-08 6 views
1

я кодирование некоторых видов поведения RL на pacman бот, и я испортил дело с одним из моих списков в одной из моих функций arg_allmax или chooseActionArrayIndexOutOfBoundsException: -1

Вот код моих класс:

package rl; 

import java.util.ArrayList; 
import java.util.Hashtable; 

public class Qlearn { 
    private double epsilon = 0.1; // Epsilon parameter for the Epsilon Greedy Strategy 
    private double alpha = 0.2; // Alpha parameter: used to influence o the refresh of Q 
    private double gamma = 0.9; // used to notice or not the feedback of the next action ; if =0 -> no feed back 

private int actions[]; 
private Hashtable< Tuple<Integer,Integer>, Double> q; // Q(s,a) : hashTable : <state,action> -> value of q 


public Qlearn(int[] actions) { 
    this.actions = actions; 
    q = new Hashtable< Tuple<Integer,Integer>, Double>(); 
} 

public Qlearn(int[] actions, double epsilon, double alpha, double gamma) { 
    this.actions = actions; 
    this.epsilon = epsilon; 
    this.alpha = alpha; 
    this.gamma = gamma; 
    q = new Hashtable< Tuple<Integer,Integer>, Double>(); 
} 

public Double getQ(int id_state, int id_action) { 
    // get the value of Q for the state of id_state and the action id_action (return 0 if the value is not in the hashtable) 
    Tuple<Integer,Integer> t = new Tuple<Integer,Integer> (id_state, id_action); // we creatte a new integer object Tubple with the value of id_state and id_action 
    Double v = q.get(t); 
    if(v != null) return v; 
    else return 0.0; 
} 

// get the argmax of a list 
public int argmax(double[] list) { 
    int arg=-1; 
    double max= 0; 
    for (int i = 0; i<list.length; i++){ 
     if (list[i]>max){ 
      max = list[i]; 
      arg = i; 
     } 
    } 
    return arg; 
} 

// get all the argmax if the argmax has several iterations 
public ArrayList<Integer> arg_allmax(double[] list) { 
    ArrayList<Integer> args = new ArrayList<Integer>(); 
    int a = argmax(list); 
    for (int i = 0; i< list.length; i++){ 
     if (list[i] == list[a]){ 
      args.add(i); 
     } 
    } 
    return args; 
} 

// get the max of the list 
public double max(double[] list) { 
    double max_ = -1e20; 
    int a = argmax(list); 
    max_ = list[a]; 
    return max_; 
} 


/* 
* Fonction that updates the hashtable 
*  for the action id_action and the state id_state 
*  if Q(s,a) had an old value, we allocate it the new value+ alpha(value - old_value) 
*  if Q(s,a) had not an old value : we allocate reward 
*/ 
public void learnQ(int id_state, int id_action, double reward, double value) { 
    Tuple<Integer,Integer> t = new Tuple<Integer,Integer>(id_state,id_action); 
    Double oldv = q.get(t); 

    if(oldv == null) { 

     q.put(t, reward); 
    } else { 

     q.put(t, oldv+alpha*(value-oldv)); 
    } 
} 

/* 
* Here is the Epsilon Greedy strategy 
*  with proba epsilon :we choose a random action 
*  avec proba 1-eps : we choose the most favorable action in fonction of Q(s,a) 
*/ 
public int chooseAction(int id_state) { 
    int action = -1; 
    if(Math.random() < epsilon) { 

     int i = (int)(Math.random()*actions.length); 
     action = actions[i]; 

    } else { 
     double[] tab = new double[actions.length]; 
     ArrayList<Integer> argmaxarray = new ArrayList<Integer>(); 
     for (int i=0; i>actions.length; i++){ 
      tab[i]=actions[i]; 
     } 
     argmaxarray=arg_allmax(tab); 
     int i=(int)(Math.random()*argmaxarray.size()); 
     action=argmaxarray.get(i); 

    } 

    return action; 
} 


/* 
* Learning after the occurence of a move 
*  1) get the most profitable potential action from Q(s',a) 
*  2) call learnQ 
*/ 
public void learn(int id_state1, int id_action1, double reward, int id_state2) { 
    int futureAction = 0; 
    futureAction = chooseAction(id_state2); 
    double maxqnew = 0; // REMPLIR 
    maxqnew = getQ(futureAction, id_state2); 


    learnQ(id_state1, id_action1, reward, reward + gamma*maxqnew); 

} 

// Affiche Q(s,a) 
private void printQvalue(int id_state) { 
    for(int action : actions) { 
     Tuple<Integer,Integer> t = new Tuple<Integer,Integer>(id_state,action); 
     Double v = q.get(t); 
     System.out.print(v+" "); 
    } 
    System.out.println(); 
} 

Вот что затмение говорит мне:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1 
    at rl.Qlearn.arg_allmax(Qlearn.java:54) 
    at rl.Qlearn.chooseAction(Qlearn.java:108) 
    at rl.Qlearn.learn(Qlearn.java:138) 

Я думаю, что это происходит где-то в другом методе selectAction, используя all_argmax fonction, но я не могу найти точную ошибку!

Вот два привлеченных метод (так что более читаемые для вас):

all_argmax:

public ArrayList<Integer> arg_allmax(double[] list) { 
    ArrayList<Integer> args = new ArrayList<Integer>(); 
    int a = argmax(list); 
    for (int i = 0; i< list.length; i++){ 
     if (list[i] == list[a]){ 
      args.add(i); 
     } 
    } 
    return args; 
} 

chooseAction:

public int chooseAction(int id_state) { 
    int action = -1; 
    if(Math.random() < epsilon) { 

     int i = (int)(Math.random()*actions.length); 
     action = actions[i]; 

    } else { 
     double[] tab = new double[actions.length]; 
     ArrayList<Integer> argmaxarray = new ArrayList<Integer>(); 
     for (int i=0; i>actions.length; i++){ 
      tab[i]=actions[i]; 
     } 
     argmaxarray=arg_allmax(tab); 
     int i=(int)(Math.random()*argmaxarray.size()); 
     action=argmaxarray.get(i); 

    } 

    return action; 
} 
+1

Это поможет, если вы: а) перевести все ваши комментарии на английский язык; б) отформатируйте свой код; c) следовать правилам именования Java в образце кода; d) свести вопрос к [mcve] (как минимальному, так и полному, ни одно из которых на данный момент не выполняется). –

+1

Теперь я удалил «первый пост при переполнении стека, спасибо, что прочитал мой маленький вопрос. Я дважды сталкиваюсь с проблемой моего кода, который я не могу разрешить». Это не имеет никакого отношения к вопросу - и, что еще хуже, поскольку это в начале вопроса, это то, что появляется на главной странице вопросов. –

+0

ok Jon Skeet Я постараюсь сделать то, что вы мне просили, извините, если способ, которым я структурировал свой пост, был неуклюжим. – drheinrich940

ответ

2

вашего IndexOutOfBoundsException происходит из-за ваш метод argmax([]), либо из-за пустого массива, либо из-за того, что все двойники в списке отрицательны.

В любом из этих случаев переменная int arg = -1 никогда не устанавливается на другое значение, чем -1, что, очевидно, выходит за границы в любом случае, так как -1 не является допустимым положение массива.

Лучший способ действий - либо проверить, является ли ваш массив пустым, прежде чем передать его на argmax, либо проверить правильность возвращаемого значения (не -1), прежде чем что-либо с ним делать. А также изменение double max = 0 на double max = Double.NEGATIVE_INFINITY

+1

' Double.MIN_VALUE' приведет к неожиданному поведению (см. Http://stackoverflow.com/ questions/3884793/why-is-double-min-value-in-not-negative), я использовал бы «Double.NEGATIVE_INFINITY» для этого варианта использования. –

+1

@ d.j.brown по совпадению Я читал тот же ответ перед вашим комментарием. Хорошая обратная связь, я обновил свой ответ – Gelunox

+0

@Gelunox спасибо, я просто изменил double max, как вы показали, и добавил небольшое сообщение allert в случае пустого списка, и теперь все работает! – drheinrich940