geva.Main.AbstractRun.java Source code

Java tutorial

Introduction

Here is the source code for geva.Main.AbstractRun.java

Source

/*
Grammatical Evolution in Java
Release: GEVA-v1.2.zip
Copyright (C) 2008 Michael O'Neill, Erik Hemberg, Anthony Brabazon, Conor Gilligan 
Contributors Patrick Middleburgh, Eliott Bartley, Jonathan Hugosson, Jeff Wrigh
    
Separate licences for asm, bsf, antlr, groovy, jscheme, commons-logging, jsci is included in the lib folder. 
Separate licence for rieps is included in src/com folder.
    
This licence refers to GEVA-v1.2.
    
This software is distributed under the terms of the GNU General Public License.
    
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
/>.
*/

/*
 * AbstractRun.java
 *
 * Created as ParameterizedState on June 12, 2007, 2:58 PM
 * Renamed to AbstractRun Nov 27 2008.
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package geva.Main;

import geva.Algorithm.AbstractAlgorithm;
import geva.Exceptions.BadParameterException;
import geva.FitnessEvaluation.FitnessFunction;
import geva.Individuals.Populations.Population;
import geva.Mapper.GEGrammar;
import geva.Operator.*;
import geva.Operator.Operations.*;
import geva.Util.Constants;
import geva.Util.Random.RandomNumberGenerator;
import geva.Util.Random.Stochastic;
import geva.Util.Statistics.IndividualCatcher;
import geva.Util.Statistics.StatCatcher;

import java.io.*;
import java.util.*;
import java.text.MessageFormat;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * AbstractRun class. Read the parameters. Some classes are dynamically loaded.
 * @author erik
 */
public abstract class AbstractRun extends State {

    private Log logger = LogFactory.getLog(AbstractRun.class);

    /**
     * Creates a new instance of AbstractRun
     */
    public AbstractRun() {
    }

    protected String propertiesFilePath;
    protected Initialiser initialiser;
    protected Properties properties;
    protected String stdOut;
    protected String stdErr;
    protected Collector collector;

    /**
     * Setup the algorithm. Read the properties. Create the modules(Operators) and operations
     * @param args arguments
     */
    public abstract void setup(String[] args);

    /**
     * Load the fitness class according to the parameters
     * @param p Properties
     * @return FitnessFunction
     */
    protected FitnessFunction getFitnessFunction(Properties p) {
        FitnessFunction fitnessFunction = null;
        String className;
        String key = Constants.FITNESS_FUNCTION;
        try {
            className = p.getProperty(key);
            if (className == null) {
                throw new BadParameterException(key);
            }
            Class clazz = Class.forName(className);
            fitnessFunction = (FitnessFunction) clazz.newInstance();
            fitnessFunction.setProperties(p);
            Class[] interfaces = clazz.getInterfaces();
            for (int i = 0; i < interfaces.length; i++) {
                if (interfaces[i].getName().equals(Stochastic.class.getName())) {
                    ((Stochastic) fitnessFunction).setRNG(this.rng);
                }
            }
        } catch (Exception e) {
            logger.error("Exception: ", e);
        }
        return fitnessFunction;
    }

    /**
     * Load a GEGrammar. Default is geva.Mapper.GEGrammar
     * @param p properties file
     * @return GEGrammar, null if getProperty failed
     */
    protected GEGrammar getGEGrammar(Properties p) {
        GEGrammar geg = null;
        String className;
        String key;
        key = Constants.GEGRAMMAR;
        try {
            className = p.getProperty(key, Constants.DEFAULT_GEGRAMMAR);
            Class clazz = Class.forName(className);
            geg = (GEGrammar) clazz.newInstance();
            geg.setProperties(p);
        } catch (IllegalAccessException e) {
            System.err.println(this.getClass().getName() + ".getGEGrammar() exception: " + e);
        } catch (ClassNotFoundException e) {
            System.err.println(this.getClass().getName() + ".getGEGrammar() exception: " + e);
            e.printStackTrace();
        } catch (InstantiationException e) {
            System.err.println(this.getClass().getName() + ".getGEGrammar() exception: " + e);
            e.printStackTrace();
        }
        return geg;
    }

    /**
     * Load and initialise the initialiser class according to the parameters
     * Defualt initialiser is the RandomInitialiser.
     * To add other initialisers expand the if-statement with another clause
     * @param g GEGrammar
     * @param rng RandomNumberGenerator
     * @param p Properties
     * @return Intialiser
     */
    protected Initialiser getInitialiser(GEGrammar g, RandomNumberGenerator rng, Properties p) {
        String className;
        String key = Constants.INITIALISER;
        try {
            className = p.getProperty(key);
            if (className == null) {
                throw new BadParameterException(key);
            }
            Class clazz = Class.forName(className);
            initialiser = (Initialiser) clazz.newInstance();
            // For RampedFullGrowInitialiser
            if (clazz.getName().equals(RampedFullGrowInitialiser.class.getName())) {
                CreationOperation fullInitialiser = new FullInitialiser(rng, g, p);
                CreationOperation growInitialiser = new GrowInitialiser(rng, g, p);
                ArrayList<CreationOperation> opL = new ArrayList<CreationOperation>();
                opL.add(fullInitialiser);
                opL.add(growInitialiser);
                ((RampedFullGrowInitialiser) initialiser).setOperations(opL);
            } else {
                // The default initialiser
                CreationOperation randomInitialiser;
                randomInitialiser = new RandomInitialiser(rng, g, p);
                initialiser.setOperation(randomInitialiser);

            }
            initialiser.setProperties(p);
            initialiser.setRNG(rng);
            initialiser.init();
        } catch (Exception e) {
            logger.error("Exception: ", e);
        }
        return initialiser;
    }

    /**
     * Load the fitness class according to the parameters
     * @param rng RandomNumberGenerator
     * @param p Properties
     * @return SelectionOperation
     */
    protected SelectionOperation getSelectionOperation(Properties p, RandomNumberGenerator rng) {
        SelectionOperation selectionOperation = null;
        String className;
        String key;
        key = Constants.SELECTION_OPERATION;
        try {
            className = p.getProperty(key);
            if (className == null) {
                throw new BadParameterException(key);
            }
            Class clazz = Class.forName(className);
            selectionOperation = (SelectionOperation) clazz.newInstance();
            selectionOperation.setProperties(p);
            if (selectionOperation instanceof Stochastic) {
                ((Stochastic) selectionOperation).setRNG(rng);
            }
        } catch (Exception e) {
            logger.error("Exception: ", e);
        }
        return selectionOperation;
    }

    /**
     * Load the fitness class according to the parameters
     * @param p Properties
     * @param rng RandomNumberGenerator
     * @param incPop incomming population
     * @param rO replacement operation
     * @return SelectionOperation
     */
    protected JoinOperator getJoinOperator(Properties p, RandomNumberGenerator rng, Population incPop,
            ReplacementOperation rO) {
        JoinOperator joinOperator = null;
        String className = "";
        String key;
        key = Constants.REPLACEMENT_TYPE;
        if (p.getProperty(key) != null) {
            if (p.getProperty(key).equals(Constants.STEADY_STATE)) {
                className = "geva.Operator.MeritReplacementStrategy";
            } else {
                if (p.getProperty(key).equals(Constants.GENERATIONAL)) {
                    className = "geva.Operator.SimpleReplacementStrategy";
                }
            }
        }
        key = Constants.REPLACEMENT_OPERATOR;
        try {
            if (p.getProperty(key) != null) {
                className = p.getProperty(key);
            }
            Class clazz = Class.forName(className);
            joinOperator = (JoinOperator) clazz.newInstance();
            joinOperator.setIncomingPopulation(incPop);
            joinOperator.setOperation(rO);
            joinOperator.setRNG(rng);
        } catch (Exception e) {
            logger.error("Exception: ", e);
        }
        return joinOperator;
    }

    /**
     * Runs the init pipeline.
     * Prints statistics from the init pipeline
     **/
    protected void init() {
        long st = System.currentTimeMillis();
        //StatCatcher stats = getStatisticsCollectionOperation().getStats();
        // Call init() in the algorithm
        // Header for the column output
        this.algorithm.init();
        long et = System.currentTimeMillis();
        this.collector = this.getCollector();
        if (this.collector != null) {
            ((StatisticsCollectionOperation) this.collector.getOperation()).printHeader();
            ((StatisticsCollectionOperation) this.collector.getOperation()).printStatistics(et - st);

        }

    }

    /**
     * Prints the collected statistics
     **/
    @SuppressWarnings({ "ConstantConditions" })
    protected void printStuff() {
        boolean printToFile = false;
        try {
            if (this.properties.getProperty(Constants.OUTPUT) != null) {
                if (!this.properties.getProperty(Constants.OUTPUT).equals("")
                        && !this.properties.getProperty(Constants.OUTPUT).equals("false")) {
                    printToFile = true;
                }
            }
        } catch (Exception e) {
            logger.warn("No output option specified! Not printing to file");
        }
        if (collector == null) {
            logger.warn("collector is null!");
        } else {
            this.collector.print(printToFile);
        }

    }

    protected IndividualCatcher getBestIndiv() {
        IndividualCatcher indivCatch = this.collector.getBest();
        return indivCatch;
    }

    /**
     * Run the loop pipeline.
     * @return int number of iterations
     **/
    protected int run() {
        long st = System.currentTimeMillis();
        // Get the number of generations
        int its = 100;// Default
        boolean stopWhenSolved = false;

        /*
         * How many fitness evaluations should be done in order to
         * count a generation, in the generational sense.
         */
        int fitnessEvaluationsPerGeneration = 1;
        try {
            String key = Constants.GENERATION;
            String value = this.properties.getProperty(key);
            if (value != null) {
                if (!value.equals("")) {
                    its = Integer.parseInt(value);
                }
            }
            key = Constants.STOP_WHEN_SOLVED;
            value = this.properties.getProperty(key);
            if (value != null) {
                if (!value.equals("")) {
                    if (value.equals(Constants.TRUE)) {
                        stopWhenSolved = true;
                    }
                }
            }
            /*
             * If Steady state is used out each generation in a
             * generational sense only has 2 fitness evaluations. Set
             * the iterations to GENERATIONS*POPULATION_SIZE/2
             */
            if (this.properties.getProperty(Constants.REPLACEMENT_TYPE, "").equals(Constants.STEADY_STATE)) {
                fitnessEvaluationsPerGeneration = Integer.parseInt(
                        this.properties.getProperty(Constants.POPULATION_SIZE, Constants.DEFAULT_POPULATION_SIZE))
                        / 2;
                its = its * fitnessEvaluationsPerGeneration;
            }
        } catch (Exception e) {
            logger.warn(e + " default generations:" + its, e);
        }
        for (int i = 1; i <= its; i++) {
            if (this.collector != null) {
                if (!foundOptimum(stopWhenSolved,
                        ((StatisticsCollectionOperation) this.collector.getOperation()).getStats())) {
                    this.algorithm.step();
                    long et = System.currentTimeMillis();
                    /* Only collect output after enough fitness
                     * evaluations to repalce the population
                     */
                    if (i % fitnessEvaluationsPerGeneration == 0) {
                        ((StatisticsCollectionOperation) this.collector.getOperation()).printStatistics(et - st);
                        st = System.currentTimeMillis();
                    }
                }
            }
        }
        return its;
    }

    /**
     * Check if the global optimum value has been found
     * @param stopWhenSolved if algorithm should terminate when the global optimum is found
     * @param stats stataistics collection
     * @return if global optimum has been found
     */
    @SuppressWarnings({ "BooleanMethodIsAlwaysInverted" })
    protected boolean foundOptimum(boolean stopWhenSolved, StatCatcher stats) {
        boolean ret = false;
        if (stopWhenSolved) {
            if (stats.getCurrentBestFitness() == 0.0) {
                ret = true;
            }
        }
        return ret;
    }

    protected MutationOperation getMutationOperation(RandomNumberGenerator rng, Properties p) {
        MutationOperation mutationOperation = null;
        String className;
        String key;
        key = Constants.MUTATION_OPERATION;
        try {
            className = p.getProperty(key);
            if (className == null || className.trim().length() == 0) {
                className = "geva.Operator.Operations.IntFlipMutation";
                System.out.println("Using default mutation [IntFlipMutation]");
            }
            Class clazz = Class.forName(className);
            mutationOperation = (MutationOperation) clazz
                    .getConstructor(RandomNumberGenerator.class, Properties.class).newInstance(rng, p);
        } catch (Exception e) {
            System.out.println("Exception: " + e);
        }
        return mutationOperation;
    }

    protected CrossoverOperation getCrossoverOperation(RandomNumberGenerator rng, Properties p) {
        CrossoverOperation crossoverOperation = null;
        String className;
        String key;
        key = Constants.CROSSOVER_OPERATION;
        try {
            className = p.getProperty(key);
            if (className == null || className.trim().length() == 0) {
                className = "geva.Operator.Operations.SinglePointCrossover";
                System.out.println("Using default crossover [SinglePointCrossover]");
            }
            Class clazz = Class.forName(className);
            crossoverOperation = (CrossoverOperation) clazz
                    .getConstructor(RandomNumberGenerator.class, Properties.class).newInstance(rng, p);
        } catch (Exception e) {
            System.out.println("Exception: " + e);
        }
        return crossoverOperation;
    }

    /**
     * helper method for getting the StatisticsCollectionOperation
     * @return Collector collector module
     **/
    protected Collector getCollector() {
        if (((AbstractAlgorithm) this.getAlgorithm()).getLoopPipeline() != null) {
            Collection<Module> m = ((AbstractAlgorithm) this.getAlgorithm()).getLoopPipeline().getModules();
            Iterator<Module> iM = m.iterator();
            Module mo;
            while (iM.hasNext()) {
                mo = iM.next();
                if (mo.getClass().getName().equals(Collector.class.getName())) {
                    if (((Collector) mo).getOperation() instanceof StatisticsCollectionOperation) {
                        return (Collector) mo;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Read the commandline arguments. Find if -h is called. Find if properties field is given
     * Prints the usage help
     * @param args Command-line arguments
     * @return booelan value of success
     **/
    @SuppressWarnings({ "IOResourceOpenedButNotSafelyClosed" })
    protected boolean commandLineArgs(String[] args) {
        boolean ret = true;
        for (int i = 0; i < args.length; i++) {
            if (args[i].startsWith("-")) {
                if (args[i].equals(Constants.HELP_FLAG)) { //print program help
                    printProgramHelp();
                    ret = false;
                } else {
                    if (args[i].equals("-" + Constants.PROPERTIES_FILE) && ((i + 1) < args.length)) { //properties file
                        this.propertiesFilePath = args[i + 1];
                    } else {
                        if (args[i].equals(Constants.VERSION_FLAG)) {
                            printVersion();
                            if (args.length == 1) {
                                ret = false;
                            }
                        }
                    }
                }
            }
        }
        return ret;
    }

    void printVersion() {
        StringBuffer sb = new StringBuffer();
        sb.append("GEVA - Grammatical evolution in JAVA");
        sb.append(System.getProperty("line.separator"));
        sb.append("Version: 1");
        sb.append(System.getProperty("line.separator"));
        sb.append("Authors: Erik Hemberg, Conor Gilligan");
        sb.append(System.getProperty("line.separator"));
        sb.append("Developed by UCD Natural Computing Research & Applications group");
        sb.append(System.getProperty("line.separator"));
        sb.append("http://ncra.ucd.ie");
        logger.info(sb.toString());
    }

    void printProgramHelp() {
        InputStream is;
        try {
            File f = new File(this.propertiesFilePath);
            is = new FileInputStream(f);
            this.properties = new Properties();
            this.properties.load(is);
            logger.info("Commandline arguments");
            logger.info("   " + Constants.HELP_FLAG + " for help");
            logger.info("   " + Constants.VERSION_FLAG + " for version");
        } catch (IOException e) {
            logger.warn(e + " no default properties file at " + this.propertiesFilePath, e);
        }
        for (Enumeration e = properties.keys(); e.hasMoreElements();) {
            logger.info("   -" + e.nextElement());
        }
    }

    /**
     * Read the default properties. Replace or add properties from the command line.
     * If the file is not found on the file system class loading from the jar is tried
     * @param args arguments
     */
    @SuppressWarnings({ "IOResourceOpenedButNotSafelyClosed" })
    protected void readProperties(String[] args) {
        ClassLoader loader;
        InputStream in;
        try {
            this.properties = new Properties();
            File f = new File(this.propertiesFilePath);
            if (!f.exists()) { // try classloading
                loader = ClassLoader.getSystemClassLoader();
                in = loader.getResourceAsStream(this.propertiesFilePath);
                this.properties.load(in);
                logger.info("Loading properties from ClassLoader and: " + this.propertiesFilePath);
            } else {
                FileInputStream is = new FileInputStream(f);
                this.properties.load(is);
                logger.info("Loading properties from file system: " + this.propertiesFilePath);
            }
            if (args != null) {
                for (int i = 0; i < args.length; i++) {
                    if (args[i].startsWith("-") && args.length > (i + 1)
                            && !args[i].equals(Constants.VERSION_FLAG)) {
                        this.properties.setProperty(args[i].substring(1), args[i + 1]);
                        i++;
                    }
                }
            }
            for (Enumeration e = properties.keys(); e.hasMoreElements();) {
                String key = (String) e.nextElement();
                logger.info(key + "=" + properties.getProperty(key, "Not defined"));
            }
        } catch (IOException e) {
            loader = ClassLoader.getSystemClassLoader();
            in = loader.getResourceAsStream(this.propertiesFilePath);
            try {
                this.properties.load(in);
            } catch (Exception ex) {
                System.err.println("Properties reading output caught:" + ex);
            }
            System.err.println(MessageFormat.format("Using default: {0} Bad:{1} Could not load:{2}",
                    this.propertiesFilePath, this.propertiesFilePath, e));
        } catch (Exception e) {
            System.err
                    .println("Could not commandline argument:" + e + " properties path:" + this.propertiesFilePath);
        }
    }

    protected void setOutput() {
        String stdOut = "";
        String stdErr = "";
        try {
            String key = Constants.STDOUT;
            String value = this.properties.getProperty(key);
            if (value != null) {
                if (!value.equals("")) {
                    stdOut = System.getProperty("user.dir") + System.getProperty("file.separator") + value + ".out";
                }
            }
            key = Constants.STDERR;
            value = this.properties.getProperty(key);
            if (value != null) {
                if (!value.equals("")) {
                    stdErr = System.getProperty("user.dir") + System.getProperty("file.separator") + value + ".err";
                }
            }
            if (!stdOut.equals("")) {
                logger.info("Redirecting stdOut to " + stdOut);
                FileOutputStream fos = new FileOutputStream(stdOut, true);
                PrintStream ps = new PrintStream(fos);
                System.setOut(ps);
            }
            if (!stdErr.equals("")) {
                logger.info("Redirecting stdErr to " + stdErr);
                FileOutputStream fos = new FileOutputStream(stdErr, true);
                PrintStream ps = new PrintStream(fos);
                System.setErr(ps);
            }
        } catch (Exception e) {
            logger.error(" std output exception", e);
        }
    }
}