Package jcgp.backend.parsers

Source Code of jcgp.backend.parsers.ChromosomeParser

package jcgp.backend.parsers;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.Scanner;

import jcgp.backend.population.Chromosome;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Input;
import jcgp.backend.population.Node;
import jcgp.backend.resources.Resources;

/**
* This class contains a method for parsing .chr files and another
* for writing .chr files from given chromosomes.
*
* @author Eduardo Pedroni
*
*/
public abstract class ChromosomeParser {

  /**
   * Use this method to parse .chr files into a given chromosome.
   * <br><br>
   * This is not fully defensive as it doesn't check for number of inputs,
   * doesn't compare rows and columns individually and doesn't account for levels back. It
   * is not viable to implement these defensive measures with the chromosome format used
   * by CGP.
   *
   * @param file the .chr file to parse from.
   * @param chromosome the chromosome to configure.
   * @param resources the experiment resources.
   */
  public static void parse(File file, Chromosome chromosome, Resources resources) {
    /*
     * Count the nodes to make sure the size of the .chr file matches the experiment parameters.
     *
     * We do this by using the scanner to get the node and output portions of the file as they
     * are separated by 3 tab characters. Every number is replaced by a single known character,
     * and the length of the string with the new characters is compared with that of a string
     * where the new known character has been removed, yielding the total number of values.
     *
     * TODO this is NOT ideal and should be refactored
     *
     */
    FileReader fr;
    try {
      fr = new FileReader(file);
    } catch (FileNotFoundException e) {
      resources.println("[Parser] Error: could not find " + file.getAbsolutePath());
      return;
    }
    Scanner in = new Scanner(fr);
   
    in.useDelimiter("\\t\\t\\t");
    String geneString = in.next().replaceAll("[0-9]+", "g");
    String outString = in.next().replaceAll("[0-9]+", "o");
    int geneCount = geneString.length() - geneString.replace("g", "").length();
    int outCount = outString.length() - outString.replace("o", "").length();
    in.close();
   
   
    // if the acquired values match the current parameters, apply them to the chromosome
    if ((geneCount == resources.nodes() * (resources.arity() + 1))
        && outCount == resources.outputs()) {
      // prepare a new scanner
      try {
        fr = new FileReader(file);
      } catch (FileNotFoundException e) {
        resources.println("[Parser] Error: could not find " + file.getAbsolutePath());
        return;
      }
      in = new Scanner(fr);
     
      resources.println("[Parser] Parsing file: " + file.getAbsolutePath() + "...");
     
      int gene;
      Connection newConnection;
      Node changingNode;
      // for all nodes, columns first
      for (int c = 0; c < resources.columns(); c++) {
        for (int r = 0; r < resources.rows(); r++) {
          // store the changing node
          changingNode = chromosome.getNode(r, c);

          // for every connection
          for (int i = 0; i < resources.arity(); i++) {
            // get connection number from the .chr file
            gene = in.nextInt();
            if (gene < resources.inputs()) {
              // connection was an input
              newConnection = chromosome.getInput(gene);
            } else {
              // connection was another node, calculate which from its number
              newConnection = chromosome.getNode((gene - resources.inputs()) % resources.rows(),
                  (gene - resources.inputs()) / resources.rows());
            }
            changingNode.setConnection(i, newConnection);
          }

          // set the function, straight indexing should work - this is not entirely
          // safe, but it is not viable to check for functionset compatibility
          changingNode.setFunction(resources.getFunction(in.nextInt()));
        }
      }

      // outputs
      for (int o = 0; o < resources.outputs(); o ++) {
        gene = in.nextInt();
        if (gene < resources.inputs()) {
          // connection was an input
          newConnection = chromosome.getInput(gene);
        } else {
          // connection was another node, calculate which from its number
          newConnection = chromosome.getNode((gene - resources.inputs()) % resources.rows(),
              (gene - resources.inputs()) / resources.rows());
        }
        chromosome.getOutput(o).setSource(newConnection);
      }
      in.close();
     
      resources.println("[Parser] File parsed successfully");
     
    } else {
      resources.println("[Parser] Error: the number of genes of the chromosome in " + file.getName() + " does not match that of the experiment");
    }
  }
 
  /**
   * Writes a chromosome into the specified .chr file.
   * <br><br>
   * The file is written in the standard .chr format and can
   * be read by the original CGP implementation.
   *
   * @param file the file to write to.
   * @param chromosome the chromosome to save.
   * @param resources a reference to the experiment's resources.
   */
  public static void save(File file, Chromosome chromosome, Resources resources) {
    PrintWriter writer;
    try {
      writer = new PrintWriter(file);
    } catch (FileNotFoundException e) {
      resources.println("[Parser] Error: could not find " + file.getAbsolutePath());
      return;
    }
   
    resources.println("[Parser] Saving to " + file.getAbsolutePath() + "...");
   
    // for all nodes, columns first
    for (int c = 0; c < resources.columns(); c++) {
      for (int r = 0; r < resources.rows(); r++) {
        for (int i = 0; i < resources.arity(); i++) {
          // print the connections, separated by spaces
          Connection conn = chromosome.getNode(r, c).getConnection(i);
          if (conn instanceof Input) {
            writer.print(" " + ((Input) conn).getIndex());
          } else if (conn instanceof Node) {
            writer.print(" " + (((((Node) conn).getColumn() + 1) * resources.inputs()) + ((Node) conn).getRow()));
          } else {
            resources.println("[Parser] Error: could not handle " + conn.getClass() + " as a subclass of Connection");
          }
        }
        // print the function numbers
        writer.print(" " + resources.getFunctionIndex(chromosome.getNode(r, c).getFunction()));
        // node is done, print tab
        writer.print("\t");
      }
    }
    // nodes are done, print two tabs to separate from output
    writer.print("\t\t");
    for (int o = 0; o < resources.outputs(); o ++) {
      Connection source = chromosome.getOutput(o).getSource();
      if (source instanceof Input) {
        writer.print(" " + ((Input) source).getIndex());
      } else if (source instanceof Node) {
        writer.print(" " + (((((Node) source).getColumn() + 1) * resources.inputs()) + ((Node) source).getRow()));
      } else {
        resources.println("[Parser] Error: could not handle " + source.getClass() + " as a subclass of Connection");
      }
    }
   
    writer.close();
   
    resources.println("[Parser] Chromosome saved successfully");
  }
 
 
  /**
   * Writes a chromosome to the console in .chr format. Note
   * that, if using a GUI console, that console must be flushed for the
   * output to appear.
   *
   * @param chromosome the chromosome to save.
   * @param resources a reference to the experiment's resources.
   */
  public static void print(Chromosome chromosome, Resources resources) {
   
    // for all nodes, columns first
    for (int c = 0; c < resources.columns(); c++) {
      for (int r = 0; r < resources.rows(); r++) {
        for (int i = 0; i < resources.arity(); i++) {
          // print the connections, separated by spaces
          Connection conn = chromosome.getNode(r, c).getConnection(i);
          if (conn instanceof Input) {
            resources.print(" " + ((Input) conn).getIndex());
          } else if (conn instanceof Node) {
            resources.print(" " + (((((Node) conn).getColumn() + 1) * resources.inputs()) + ((Node) conn).getRow()));
          } else {
            resources.println("[Parser] Error: could not handle " + conn.getClass() + " as a subclass of Connection");
          }
        }
        // print the function numbers
        resources.print(" " + resources.getFunctionIndex(chromosome.getNode(r, c).getFunction()));
        // node is done, print tab
        resources.print("\t");
      }
    }
    // nodes are done, print two tabs to separate from output
    resources.print("\t\t");
    for (int o = 0; o < resources.outputs(); o ++) {
      Connection source = chromosome.getOutput(o).getSource();
      if (source instanceof Input) {
        resources.print(" " + ((Input) source).getIndex());
      } else if (source instanceof Node) {
        resources.print(" " + (((((Node) source).getColumn() + 1) * resources.inputs()) + ((Node) source).getRow()));
      } else {
        resources.println("[Parser] Error: could not handle " + source.getClass() + " as a subclass of Connection");
      }
    }
   
    resources.println("");
  }
}
TOP

Related Classes of jcgp.backend.parsers.ChromosomeParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.