Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.util.concurrent.TimeUnit;
- import java.util.*;
- import java.io.*;
- import java.lang.*;
- public class AlgoritmoEvolutivo{
- static BufferedReader reader;
- static ArrayList<int[]> list = new ArrayList<int[]>(); //La estructura de int[] es: {x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,time}
- static String fileName = "plan.plan"; //El archivo que se leera.
- static int[][] matrix; //La matriz donde se guarda el plano.
- static int validWallValue = 32; //Valor personalizado que usara la matriz para determinar paredes validas
- static int validWallCount = 0; //Cantidad de paredes validas, utilizada en algoritmos de generacion al azar.
- static int nIteraciones = 30;
- static int nIndividuos = 30;
- static int nMutaciones = 5;
- //Cantidad de vectores (conjunto de 5 puertas) por iteracion.
- public static void main(String[]args){
- int[] map_lenght = readBlueprintSize();
- matrix = new int[map_lenght[1]+1][map_lenght[0]+1];
- int[] vector = new int[11];
- populateMatrix();
- setValidWalls();
- printMatrix();
- for(int i=0; i < nIndividuos; i++){
- list.add(evaluate(generateRandomTestValues()));
- }
- writeList();
- //Comienzan las iteraciones.
- for(int i = 1; i<=nIteraciones; i++){
- Random rng = new Random();
- //1. ordenar poblacion
- //inserte codigo aqui
- //2. De los 10 más optimos en la lista, se cruzan en pares aleatorios.
- //De este cruzamiento se generan 5 hijos que se agregan al fondo de la lista.
- List<int[]> topTen = list.subList(0,10);
- ArrayList<int[]> bottomFive = new ArrayList<int[]>();
- while(topTen.size()>0){
- //extrae padre A y posicion aleatoria.
- int a = rng.nextInt(topTen.size()-1);
- int[] parentA = list.get(a);
- topTen.remove(a);
- //extrae padre B y posicion aleatoria.
- int b = rng.nextInt(topTen.size()-1);
- int[] parentB = list.get(b);
- topTen.remove(b);
- bottomFive.add(crossValues(evaluate(parentA),evaluate(parentB)));
- }
- //Remueve los ultimos 5 objetos de la lista.
- for(int k = list.size()-5; k < list.size(); k++){
- list.remove(k);
- }
- //Agrega los 5 nuevos objetos a la lista.
- for(int j=0;j<bottomFive.size();i++){
- list.add(bottomFive.get(j));
- }
- //3. Muta n valores al azar de los individuos en medio (no top ten y no bottom five)
- for(int j=0;j<nMutaciones;j++){
- int aux = rng.nextInt(list.size()-16)+10;
- list.set(aux,evaluate(mutateValue(list.get(aux),3)));
- }
- //4. calcular promedio y encontrar el mayor
- int optimo = 10000;
- int promedio = 0;
- for(int j=0;j<list.size();j++){
- int aux = list.get(j)[10];
- if(aux < 9000){
- promedio += aux;
- if(aux < optimo){
- optimo = aux;
- }
- }
- }
- System.out.println("Iteracion n."+i+": Mejor valor: "+optimo+", Promedio: "+promedio);
- writeList();
- }
- }
- //Evalua el vector y devuelve el tiempo de la simulacion. Este metodo componen
- //la escritura de doors.plan, la ejecucion de NetLogo y la lectura de seconds.output.
- public static int[] evaluate(int[] vector){
- writeDoorsPlan(vector);
- execNetLogo();
- vector[10] = readDoorsTime();
- return vector;
- }
- //Calcula las dimensiones del plano en fileName, devuelve un array de dos valores
- //con el ancho y alto del plano en ese orden.
- public static int[] readBlueprintSize(){
- String line;
- int map_width = 0;
- int map_height = 0;
- int temp;
- openFile(fileName);
- try{
- line = reader.readLine();
- do{
- temp = Integer.parseInt(line.substring(0,line.indexOf(' ')));
- if (temp > map_width) map_width = temp;
- temp = Integer.parseInt(line.substring(line.indexOf(' ')+1,line.lastIndexOf(' ')));
- if (temp > map_height) map_height = temp;
- line = reader.readLine();
- }while(line != null);
- }catch(IOException e){
- System.out.println("ERROR: Fallo al leer el archivo '"+fileName+"'.");
- }
- int[] result = {map_width,map_height};
- closeFile();
- return result;
- }
- //Populate the matrix with the values in the file "fileName".
- public static void populateMatrix(){
- int temp_x;
- int temp_y;
- int value;
- String line;
- openFile(fileName);
- try{
- line = reader.readLine();
- do{
- temp_x = Integer.parseInt(line.substring(0,line.indexOf(' ')));
- temp_y = Integer.parseInt(line.substring(line.indexOf(' ')+1,line.lastIndexOf(' ')));
- value = Integer.parseInt(line.substring(line.lastIndexOf(' ')+1));
- matrix[temp_y][temp_x] = value;
- line = reader.readLine();
- }while(line != null);
- }catch(IOException e){
- System.out.println("ERROR: Fallo al leer el archivo '"+fileName+"'.");
- }
- }
- //Analiza la estructura de la matriz, reconoce las paredes que sirven
- //para la evaluacion. Paredes seleccionadas utilizan el valor 32 en la matriz.
- public static void setValidWalls(){
- validWallCount = 0;
- for (int i = 0; i < matrix.length; i++){
- for (int j = 0; j < matrix[i].length; j++){
- if(matrix[i][j] == 64){
- try{
- if(matrix[i][j+1] == 2 && matrix[i][j-1] == 0) matrix[i][j] = validWallValue;
- if(matrix[i][j-1] == 2 && matrix[i][j+1] == 0) matrix[i][j] = validWallValue;
- if(matrix[i+1][j] == 2 && matrix[i-1][j] == 0) matrix[i][j] = validWallValue;
- if(matrix[i-1][j] == 2 && matrix[i+1][j] == 0) matrix[i][j] = validWallValue;
- if(matrix[i][j] == validWallValue) validWallCount++;
- }catch(ArrayIndexOutOfBoundsException e){
- System.out.println("ADVERTENCIA: Pared detectada en los ejes de la matriz.");
- }
- }
- }
- }
- }
- //Genera 5 numeros al azar que sirven para elegir de forma aleatoriamente las coordenadas de
- //5 paredes que esten categorizadas como validas en la matriz. El metodo devuelve un vector
- //(array) de integrales de 10 valores que conforman las coordenadas de las paredes a usar, en el
- //orden {x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,time = 0}.
- public static int[] generateRandomTestValues(){
- Random rng = new Random();
- //Propiedades de Random: ints son minimo y maximo, distinct es que no se repitan, limit es
- //la cantidad de randoms que se generara, exporta a un array.
- int[] randomNum = new Random().ints(1, validWallCount+1).distinct().limit(5).toArray();
- int[] randomCoord = new int[11];
- int temp_count = 0; //Cuenta desde 0 hasta la cantidad total de paredes validas.
- int index_pointer = 0; //Puntero para el array de cordinadas.
- for (int i = 0; i < matrix.length; i++){
- for (int j = 0; j < matrix[i].length; j++){
- if(matrix[i][j] == validWallValue){
- temp_count++;
- if (arrayContains(randomNum,temp_count)){
- try{
- randomCoord[index_pointer] = i;
- randomCoord[index_pointer+1] = j;
- index_pointer = index_pointer +2;
- }catch(ArrayIndexOutOfBoundsException e){
- System.out.println("ERROR: Algo salio mal al obtener paredes al azar.");
- }
- }
- }
- }
- }
- //System.out.println("Random: ("+randomCoord[0]+","+randomCoord[1]+") ("+randomCoord[2]+","+randomCoord[3]+") ("+randomCoord[4]+","+randomCoord[5]+") ("+randomCoord[6]+","+randomCoord[7]+") ("+randomCoord[8]+","+randomCoord[9]+").");
- return randomCoord;
- }
- //Algoritmo de cruzamiento, se toman dos vectores llamados padres, y se genera
- public static int[] crossValues(int[] parent1, int[] parent2){
- Random rng = new Random();
- int[] heritage = new Random().ints(0,2).limit(5).toArray();
- int[] child = parent1.clone();
- int index_pointer = 0; //Puntero para el array de cordinadas.
- for(int k = 0; k < heritage.length; k++){
- if(heritage[k] == 1){
- child[k*2] = parent2[k*2];
- child[k*2+1] = parent2[k*2+1];
- }
- }
- child[10] = 0;
- return child;
- }
- //Algoritmo de mutación, selecciona una posición al azar del padre para tomar coordenadas (x,y) y posteriormente mutarlas
- public static int[] mutateValue(int[] parent, int mutations){
- Random rng = new Random();
- for(int i=0;i<mutations;i++){
- //selecciona par al azar
- int index = rng.nextInt(5)*2;
- int [] selected = {parent[index],parent[index+1]};
- //selecciona una coordenada al azar y le suma un numero al azar entre -5 y 5
- //si al sumar en una coordenada el resultado no es una pared válida, se repite el proceso para la otra coordenada
- //si ninguna combinacion es valida, no se realizan cambios sobre el arreglo original
- try{
- switch(rng.nextInt(2)){
- case 0:
- selected[0] += rng.nextInt(11)-5;
- if(matrix[selected[0]][parent[index+1]]==validWallValue){
- parent[index]=selected[0];
- }
- else{
- selected[1] += rng.nextInt(11)-5;
- if(matrix[parent[index]][selected[1]]==validWallValue){
- parent[index+1]=selected[1];
- }
- }
- break;
- case 1:
- selected[1] += rng.nextInt(11)-5;
- if(matrix[parent[index]][selected[1]]==validWallValue){
- parent[index+1]=selected[1];
- }
- else{
- selected[0] += rng.nextInt(11)-5;
- if(matrix[selected[0]][parent[index+1]]==validWallValue){
- parent[index]=selected[0];
- }
- }
- break;
- }
- }catch (ArrayIndexOutOfBoundsException e){
- System.out.println("ADVERTENCIA: La mutacion proboco salida de Arrays.");
- }
- }
- return parent;
- }
- //Revisa si el valor esta dentro de un array de INTs.
- public static boolean arrayContains(int[] array, int value){
- for(int x = 0; x < array.length; x++){
- if(array[x] == value) return true;
- }
- return false;
- }
- //Imprime la matriz en sistema. Los simbolos son:
- // "_" : Espacio interior
- // "." : Espacio exterior
- // "X" : Pared interior
- // "0" : Pared exterior (Valida)
- public static void printMatrix(){
- for (int i = 0; i < matrix.length; i++){
- for (int j = 0; j < matrix[i].length; j++){
- if (matrix[i][j] == 64) System.out.print("X");
- else if (matrix[i][j] == 2) System.out.print(".");
- else if (matrix[i][j] == validWallValue) System.out.print("0");
- else System.out.print("_");
- }System.out.println();
- }
- }
- //Abre el archivo de nombre "name" en el BufferedReader estatico.
- public static void openFile(String name){
- try{
- reader = new BufferedReader(new FileReader(name));
- }catch(IOException e){
- System.out.println("ERROR: Archivo '"+name+"' no existe.");
- }
- }
- //Cierra el archivo actual en el BufferedReader estatico.
- public static void closeFile(){
- try{
- reader.close();
- }catch (IOException e){
- System.out.println("ERROR: Fallo al cerrar el archivo.");
- }
- }
- //Genera el archivo "doors.plan" con las coordenadas especificadas en
- //el argumento de entrada, en el orden (x1,y1,x2,y2,x3,y3,x4,y4,x5,y5)
- public static void writeDoorsPlan(int[] coords){
- try{
- PrintWriter writer = new PrintWriter("doors.plan", "UTF-8");
- for(int z = 0; z < 10; z = z + 2) writer.println(coords[z]+" "+coords[z+1]);
- writer.close();
- }catch (IOException e) {
- System.out.println("ERROR: Fallo al escribir doors.plan en el dispositivo. ("+e.getMessage()+")" );
- }catch (ArrayIndexOutOfBoundsException e){
- System.out.println("ERROR: Algo salio mal leer los indices de las cordenadas. ("+e.getMessage()+")");
- }
- }
- public static void writeTimeout(){
- try{
- PrintWriter writer = new PrintWriter("seconds.output", "UTF-8");
- writer.println("999999");
- writer.close();
- }catch (IOException e) {
- System.out.println("ERROR: Fallo al escribir seconds.output en el dispositivo. ("+e.getMessage()+")" );
- }
- }
- //Lee el archivo "seconds.output" que genera NetLogo, devuelve el tiempo en el archivo.
- public static int readDoorsTime(){
- int time = -1;
- openFile("seconds.output");
- try{
- time = Integer.parseInt(reader.readLine());
- }catch (IOException e){
- System.out.println("ERROR: Problema al leer el valor del archivo seconds.output.");
- }
- closeFile();
- return time;
- }
- //Ejecuta NetLogo en linea de comando
- public static void execNetLogo(){
- try {
- System.out.println("Simulando...");
- Process p = Runtime.getRuntime().exec("java -Xmx1024m -Dfile.encoding=UTF-8 -cp NetLogo.jar org.nlogo.headless.Main --model escape4.nlogo --experiment simulation");
- if(!p.waitFor(10, TimeUnit.SECONDS)) {
- p.destroy();
- System.out.println("ADVERTENCIA: Expiro el tiempo de simulación.");
- writeTimeout();
- }else{
- System.out.println("Simulacion completa.");
- }
- } catch (IOException ex) {
- System.out.println("ERROR: "+ex);
- } catch (InterruptedException ie){
- System.out.println("ERROR: "+ie);
- }
- }
- //Determina los dos numeros mas pequeños entre 4, utilizado para determinar los nuevos
- //padres en el cruzamiento. El numero usa la escala binaria para representar los dos
- //numeros (num1 = 1, num2 = 2, num3= 4, num4= 8).
- public static int compareNum(int num1, int num2, int num3, int num4){
- if(num1 < num2 && num1 < num3 && num1 < num4){
- if(num2 < num3 && num2 < num4) return 3;
- else if(num3 < num4) return 5;
- else return 9;
- }else if (num2 < num3 && num2 < num4){
- if(num1 < num3 && num1 < num4) return 3;
- else if(num3 < num4) return 6;
- else return 10;
- }else if (num3 < num4){
- if(num1 < num2 && num1 < num4) return 5;
- else if(num2 < num4) return 6;
- else return 12;
- }else{
- if(num1 < num2 && num1 < num3) return 9;
- else if(num2 < num3) return 10;
- else return 12;
- }
- }
- public static void writeList(){
- int[] temp;
- try{
- PrintWriter writer = new PrintWriter("log.csv", "UTF-8");
- for(int z = 0; z < list.size(); z++){
- temp = list.get(z);
- writer.print(temp[10]);
- if(z != list.size()-1) writer.print(",");
- }
- writer.println();
- writer.close();
- }catch (IOException e) {
- System.out.println("ERROR: Fallo al escribir doors.plan en el dispositivo. ("+e.getMessage()+")" );
- }catch (ArrayIndexOutOfBoundsException e){
- System.out.println("ERROR: Algo salio mal leer los indices de las cordenadas. ("+e.getMessage()+")");
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement