/*
  Copyright 2012 by Luca Manzoni
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/

package ec.app.klandscapes;

import ec.app.klandscapes.func.KLandscapeTree;
import ec.*;
import ec.gp.*;
import ec.gp.koza.*;
import ec.simple.*;
import ec.util.*;

import java.util.*;

/**
 * KLandscapes implements the K-Landscapes problem of Vanneschi,
 * Castelli and Manzoni. See the README.txt.  
 *
 

Parameters

base.data
classname, inherits or == ec.app.klandscapes.KLandscapesData
(the class for the prototypical GPData object for the KLandscapes problem)
base.k-value
Integer specifying the amount of epistasis in fitness contributions Values from 0 upwards.

Parameter bases

base.data species (the GPData object)
* * @author Luca Manzoni * @version 1.0 */ public class KLandscapes extends GPProblem implements SimpleProblemForm { // Score of the nodes. Functionals (positions 0 and 1) and terminals (positions from 2 to 5) double nodeScore[]; // Score fo the edges. Row: functionals. Columns: funcionals + terminals double edgeScore[][]; // Best possible fitness. Must be not negative. double bestFitness; // The K of the K-Landscapes. It is an index of epistasis. It has // integer values from 2 upwards, in the paper's experimental // section, but can take on values 0 and 1. int k; String P_PROBLEMNAME = "k-landscapes"; String P_KVALUE = "k-value"; public void setup(final EvolutionState state, final Parameter base) { super.setup(state,base); state.output.exitIfErrors(); Parameter kval = new Parameter(state.P_EVALUATOR).push(P_PROBLEM).push(P_PROBLEMNAME).push(P_KVALUE); k = state.parameters.getInt(kval,null,0); // System.out.println("K = " + k); for(int i = 0 ; i < indices.length; i++) indices[i] = -1; indices['A' - 'A'] = 0; indices['B' - 'A'] = 1; indices['X' - 'A'] = 2; indices['Y' - 'A'] = 3; indices['Z' - 'A'] = 4; indices['W' - 'A'] = 5; // now do some initialization MersenneTwisterFast r = state.random[0]; nodeScore = new double[6]; edgeScore = new double[2][6]; for (int i = 0; i < 6; i++) { nodeScore[i] = 2*r.nextDouble() -1; } // We need to assure that the best fitness is positive (to normalize it to 1) // A method to do this is to have at least one terminal symbol with a positive score. boolean ok = false; for (int i = 2; i < 6; i++) { if (nodeScore[i] > 0) ok = true; } if (!ok) nodeScore[2] = r.nextDouble(); for (int i = 0; i < 2; i++) { for (int j = 0; j < 6; j++) { edgeScore[i][j] = r.nextDouble(); } } bestFitness = computeBestFitness(); } // doesn't need to be cloned int[] indices = new int[256]; // we assume we only have letters, and 0 means "no sucessor" int getIndex(char c) { return indices[c - 'A']; } public void evaluate( final EvolutionState state, final Individual ind, final int subpopulation, final int threadnum) { if (!ind.evaluated) { double score = fitness(((GPIndividual) ind).trees[0].child); SimpleFitness f = ((SimpleFitness) ind.fitness); f.setFitness(state, score, score==1.0); ind.evaluated = true; } } double fitness(GPNode root) { // Compute the penality (it increases with the difference in depth between the tree and k. double penalty = 1.0/(1+Math.abs(k+1-root.depth())); return penalty*fitnessHelper(root)/bestFitness; } // We recursively search for the subtree with the maximal "score" double fitnessHelper(GPNode node) { double max = subtreeFitness(node,k); for (int i = 0; i < node.children.length; i++) { GPNode child = node.children[i]; double tmp = fitnessHelper(child); if (tmp > max) max = tmp; } return max; } double subtreeFitness(GPNode node, int depth) { int index = getIndex(((KLandscapeTree) node).value()); double score = nodeScore[index]; if (depth == 0 || index > 1) //If we have reached the maximum depth (or we have found a terminal) return score; for (int i = 0; i < node.children.length; i++) { GPNode child = node.children[i]; int childindex = getIndex(((KLandscapeTree) child).value()); //We recursively compute the "score" of the subtree score += (1+edgeScore[index][childindex])*subtreeFitness(child,depth-1); } return score; } double computeBestFitness() { // This is a dynamic programming kludge. double ttable[][] = new double[k][2]; double ftable[][] = new double[k+1][2]; for (int i = 0; i < 2; i++) { ftable[0][i] = nodeScore[i]; } // Case 1: the optimum hase depth at most k for (int i = 0; i < k; i++) { for (int j = 0; j < 2; j++) { if (i == 0) { double max = (1+edgeScore[j][2])*nodeScore[2]; for (int h = 3; h < 6; h++) { double tmp = (1+edgeScore[j][h])*nodeScore[h]; if (tmp > max) max = tmp; } ttable[i][j] = nodeScore[j] + 2*max; } else { double max = (1+edgeScore[j][0])*ttable[i-1][0]; for (int h = 1; h < 2; h++) { double tmp = (1+edgeScore[j][h])*ttable[i-1][h]; if (tmp > max) max = tmp; } ttable[i][j] = nodeScore[j] + 2*max; } } } // Case 2: the optimum has depth k+1 for (int i = 1; i < k+1; i++) { for (int j = 0; j < 2; j++) { double max = (1+edgeScore[j][0])*ftable[i-1][0]; for (int h = 1; h < 2; h++) { double tmp = (1+edgeScore[j][h])*ftable[i-1][h]; if (tmp > max) max = tmp; } ftable[i][j] = nodeScore[j] + 2*max; } } double best = nodeScore[2]; for (int i = 3; i < 6; i++) { if (nodeScore[i] > best) best = nodeScore[i]; } for (int i = 0; i < k; i++) { for (int j = 0; j < 2; j++) { if (ttable[i][j] > best) best = ttable[i][j]; } } for (int i = 0; i < 2; i++) { if (0.5*ftable[k][i] > best) best = 0.5*ftable[k][i]; } return best; } public Object clone() { KLandscapes tmp = (KLandscapes)(super.clone()); tmp.nodeScore = new double[6]; tmp.edgeScore = new double[2][6]; tmp.bestFitness = bestFitness; tmp.k = k; for (int i = 0; i < 6; i++) { tmp.nodeScore[i] = nodeScore[i]; for (int j = 0; j < 2; j++) { tmp.edgeScore[j][i] = edgeScore[j][i]; } } return tmp; } }

Ads help maintain this website.