geva.Operator.Operations.GrowInitialiser.java Source code

Java tutorial

Introduction

Here is the source code for geva.Operator.Operations.GrowInitialiser.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/>.
/>.
*/

package geva.Operator.Operations;

import geva.Exceptions.BadParameterException;
import geva.Exceptions.InitializationException;
import geva.Individuals.*;
import geva.Individuals.FitnessPackage.BasicFitness;
import geva.Individuals.FitnessPackage.Fitness;
import geva.Mapper.GEGrammar;
import geva.Mapper.Production;
import geva.Mapper.Rule;
import geva.Mapper.Symbol;
import geva.Util.Constants;
import geva.Util.Enums;
import geva.Util.Random.RandomNumberGenerator;
import geva.Util.Random.Stochastic;
import geva.Util.Structures.NimbleTree;
import geva.Util.Structures.TreeNode;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Class for growing individuals to the maximum derrivationTree size of maxDepth
 * @author erikhemberg
 */
public class GrowInitialiser implements CreationOperation, Stochastic {

    private static Log logger = LogFactory.getLog(GrowInitialiser.class);

    protected Genotype genotype;
    protected GEChromosome chromosome;
    protected RandomNumberGenerator rng;
    protected int maxDepth;
    protected int minDepth;
    protected GEGrammar grammar;
    protected int initChromSize;
    protected int extraCodons; //Used when createing ADF

    /**
     * New instance
     * @param rng random number generator
     * @param gegrammar grammatical evolution grammar
     * @param maxDepth max growth depth of tree
     */
    public GrowInitialiser(RandomNumberGenerator rng, GEGrammar gegrammar, int maxDepth) {
        this.grammar = gegrammar;
        this.maxDepth = maxDepth;
        this.minDepth = 0;
        this.initChromSize = 100; //Default initial chrom size
        this.rng = rng;
        this.extraCodons = 0;
    }

    /**
     * New instance
     * @param rng random number generator
     * @param gegrammar grammatical evolution grammar
     * @param p properties
     */
    public GrowInitialiser(RandomNumberGenerator rng, GEGrammar gegrammar, Properties p) {
        this.grammar = gegrammar;
        setProperties(p);
        this.minDepth = 0;
        this.rng = rng;
        this.extraCodons = 0;
    }

    public void setRNG(RandomNumberGenerator m) {
        this.rng = m;
    }

    public RandomNumberGenerator getRNG() {
        return this.rng;
    }

    public void setProperties(Properties p) {
        int value;
        try {
            String key = Constants.MAX_DEPTH;
            value = Integer.parseInt(p.getProperty(key));
            if (value < 1) {
                throw new BadParameterException(key);
            }
        } catch (Exception e) {
            value = 10;
            logger.warn(e + " using default: " + value, e);
        }
        this.maxDepth = value;
        String std = Constants.DEFAULT_CHROMOSOME_SIZE;
        String key = Constants.INITIAL_CHROMOSOME_SIZE;
        try {
            value = Integer.parseInt(p.getProperty(key, std));
            if (value < 1) {
                throw new BadParameterException(key);
            }
        } catch (Exception e) {
            value = Integer.parseInt(std);
            logger.warn(e + " for " + key + " using default: " + value, e);
        }
        this.initChromSize = value;
    }

    /**
     *  Creates an geva.Individuals
     */
    public Individual createIndividual() {
        GEGrammar gram = GEGrammar.getGrammar(this.grammar);
        Phenotype phenotype = new Phenotype();
        int[] codons = new int[this.initChromSize];
        GEChromosome chrom = new GEChromosome(this.initChromSize, codons);
        // If the given max derivation tree depth is less than the max depth of
        // - the tree, set the max derivation tree depth to the max depth of the
        // - the tree.

        if (gram.getMaxDerivationTreeDepth() < this.maxDepth) {
            gram.setMaxDerivationTreeDepth(this.maxDepth);
        }
        chrom.setMaxChromosomeLength(gram.getMaxChromosomeLengthByDepth());
        Genotype geno = new Genotype(1, chrom);
        Fitness fitness = new BasicFitness();
        GEIndividual gei = new GEIndividual(gram, phenotype, geno, fitness);
        return gei;
    }

    /**
     * Get minimum depth of tree
     * @return minimum depth
     */
    public int getMinDepth() {
        return minDepth;
    }

    /**
     * Set minimum depth
     * @param minDepth minumum depth
     */
    public void setMinDepth(int minDepth) {
        this.minDepth = minDepth;
    }

    /**
     * Set maximum depth of tree
     * @param i max depth
     */
    public void setMaxDepth(int i) {
        this.maxDepth = i;
    }

    /**
     * Get max depth of tree
     * @return max depth
     */
    public int getMaxDepth() {
        return this.maxDepth;
    }

    public void doOperation(Individual operand) {
        GEIndividual ind = (GEIndividual) operand;
        //ind = new GEIndividual(ind);
        ind.setGenotype(this.getGenotype(((GEChromosome) ind.getGenotype().get(0)).getMaxChromosomeLength()));
        //ind.getMapper().setGenotype(ind.getGenotype().get(0));

    }

    // Implement
    public void doOperation(List<Individual> operands) {
    }

    /** Creates a genotype by building a tree to the most maxDepth for one branch.
     *  WHAT TO DO IF SIZE IS LARGER THAN MAX_LENGTH*WRAPS??
     *  @return A valid Genotype
     **/
    public Genotype getGenotype(int maxLength) {
        genotype = new Genotype();
        chromosome = new GEChromosome(this.initChromSize);
        chromosome.setMaxChromosomeLength(maxLength);
        genotype.add(chromosome);
        // Initialise derrivationTree
        NimbleTree<Symbol> dt = new NimbleTree<Symbol>();
        TreeNode<Symbol> tn = new TreeNode<Symbol>();
        tn.setData(grammar.getStartSymbol());
        dt.populateStack();
        dt.setRoot(tn);
        dt.setCurrentNode(dt.getRoot());
        // Grow tree
        grow(dt);
        if (this.extraCodons > 0) {
            for (int i = 0; i < this.extraCodons; i++) {
                this.chromosome.add(this.rng.nextInt(Integer.MAX_VALUE));
            }
        }
        return genotype;
    }

    /**
     * Recursively builds a tree.
     * @param dt Tree to grow on
     * @return If the tree is valid
     **/
    public boolean grow(NimbleTree<Symbol> dt) {
        Rule rule;
        Iterator<Production> prodIt;
        ArrayList<Integer> possibleRules = new ArrayList<Integer>();
        Production prod;
        int prodVal;
        boolean result;
        int newMaxDepth;
        Iterator<Symbol> symIt;
        Symbol symbol;

        try {
            if (dt.getCurrentNode().getData().getType() == Enums.SymbolType.TSymbol) {
                //Check if it is for ADF
                if (dt.getCurrentNode().getData().getSymbolString().contains("BRR")) {
                    this.extraCodons++;
                }
                return true;
            }
            if (dt.getCurrentLevel() > this.maxDepth) {
                //System.out.println("Too deep:"+dt.getCurrentLevel()+">"+this.maxDepth);
                return false;
            }
            rule = grammar.findRule(dt.getCurrentNode().getData());
            if (rule != null) {
                prodIt = rule.iterator();
                possibleRules.clear();
                int ii = 0;
                //System.out.print(rule.getLHS().getSymbolString()+" minD:"+rule.getMinimumDepth()+" maxD:"+maxDepth+" cD:"+dt.getCurrentLevel());

                while (prodIt.hasNext()) {
                    prod = prodIt.next();
                    if ((dt.getCurrentLevel() + prod.getMinimumDepth()) <= this.maxDepth) {
                        possibleRules.add(ii);
                    }
                    ii++;
                }
                //System.out.print(" \n");
                if (possibleRules.isEmpty()) {
                    //System.out.println("EmptyPossible rules:"+rule);
                    return false;
                } else {
                    prodVal = this.rng.nextInt(possibleRules.size());
                    int modVal = possibleRules.get(prodVal);
                    int tmp1 = this.rng.nextInt((Integer.MAX_VALUE - rule.size()));
                    int tmp;
                    int mod = tmp1 % rule.size();
                    int diff;
                    if (mod > modVal) {
                        diff = mod - modVal;
                        tmp = tmp1 - diff;
                    } else {
                        diff = modVal - mod;
                        tmp = tmp1 + diff;
                    }
                    int newMod = tmp % rule.size();
                    if (newMod != modVal) {
                        logger.info("modVal:" + modVal + " tmp1:" + tmp1 + " mod:" + mod + " tmp:" + tmp
                                + " rule.size():" + rule.size() + " newMod:" + newMod);

                    }
                    if (rule.size() > 1) {
                        this.chromosome.add(tmp); //correct choosing of production??
                        prod = rule.get(possibleRules.get(prodVal));
                    } else {
                        // only one rule does not use a codon
                        //this.chromosome.add(tmp); //correct choosing of production??
                        prod = rule.get(0);
                    }
                }
                result = true;
                newMaxDepth = dt.getDepth();
                symIt = prod.iterator();
                while (symIt.hasNext() && result) {
                    symbol = symIt.next();
                    dt.addChild(symbol);
                    dt.setCurrentNode(dt.getCurrentNode().getEnd());
                    dt.setCurrentLevel(dt.getCurrentLevel() + 1);
                    result = grow(dt);
                    dt.setCurrentLevel(dt.getCurrentLevel() - 1);
                    if (newMaxDepth < dt.getDepth()) {
                        newMaxDepth = dt.getDepth();
                    }
                }
                chromosome.setValid(result);
                dt.setDepth(newMaxDepth);
                return result;
            } else {
                if (!checkGECodonValue(dt)) {
                    throw new InitializationException(
                            "Non-existent rule, maybe GECODON not yet impelemnted. Could not find"
                                    + dt.getCurrentNode().getData().getSymbolString());
                }
                return true;
            }
        } catch (InitializationException e) {
            logger.error("Exception initializing", e);
            return false;
        }
    }

    /**
     * Check if it is a GECodonValue. Sapecific construct for inserting informatino into the grammar
     * @param dt tree
     * @return if it is a GECodonValue
     */
    @SuppressWarnings({ "BooleanMethodIsAlwaysInverted" })
    protected boolean checkGECodonValue(NimbleTree<Symbol> dt) {
        boolean ret = false;
        if (dt.getCurrentNode().getData().getSymbolString().contains(Constants.GE_CODON_VALUE)) {
            this.chromosome.add(this.rng.nextInt(Integer.MAX_VALUE));
            ret = true;
        }
        return ret;
    }
}