/*
  Copyright 2006 by Sean Luke
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/


package ec.vector;

import ec.*;
import ec.util.*;
import java.io.*;

/*
 * IntegerVectorIndividual.java
 * Created: Tue Mar 13 15:03:12 EST 2001
 */

/**
 * IntegerVectorIndividual is a VectorIndividual whose genome is an array of ints.
 * Gene values may range from species.mingene(x) to species.maxgene(x), inclusive.
 * The default mutation method randomizes genes to new values in this range,
 * with species.mutationProbability.
 *

 * 

From ec.Individual: *

In addition to serialization for checkpointing, Individuals may read and write themselves to streams in three ways. * *

*

In general, the various readers and writers do three things: they tell the Fitness to read/write itself, * they read/write the evaluated flag, and they read/write the gene array. If you add instance variables to * a VectorIndividual or subclass, you'll need to read/write those variables as well.

Default Base
vector.int-vect-ind * @author Sean Luke * @version 1.0 */ public class IntegerVectorIndividual extends VectorIndividual { public static final String P_INTEGERVECTORINDIVIDUAL = "int-vect-ind"; public int[] genome; public Parameter defaultBase() { return VectorDefaults.base().push(P_INTEGERVECTORINDIVIDUAL); } public Object clone() { IntegerVectorIndividual myobj = (IntegerVectorIndividual) (super.clone()); // must clone the genome myobj.genome = (int[])(genome.clone()); return myobj; } public void setup(final EvolutionState state, final Parameter base) { super.setup(state,base); // actually unnecessary (Individual.setup() is empty) Parameter def = defaultBase(); if (!(species instanceof IntegerVectorSpecies)) state.output.fatal("IntegerVectorIndividual requires an IntegerVectorSpecies", base, def); IntegerVectorSpecies s = (IntegerVectorSpecies) species; genome = new int[s.genomeSize]; } public void defaultCrossover(EvolutionState state, int thread, VectorIndividual ind) { IntegerVectorSpecies s = (IntegerVectorSpecies) species; IntegerVectorIndividual i = (IntegerVectorIndividual) ind; int tmp; int point; int len = Math.min(genome.length, i.genome.length); if (len != genome.length || len != i.genome.length) state.output.warnOnce("Genome lengths are not the same. Vector crossover will only be done in overlapping region."); switch(s.crossoverType) { case VectorSpecies.C_ONE_POINT: // point = state.random[thread].nextInt((len / s.chunksize)+1); // we want to go from 0 ... len-1 // so that there is only ONE case of NO-OP crossover, not TWO point = state.random[thread].nextInt((len / s.chunksize)); for(int x=0;x point) { int p = point0; point0 = point; point = p; } for(int x=point0*s.chunksize;x point) { int p = point0; point0 = point; point = p; } for(int x=point0*s.chunksize;x max || u < min || u > max)) { genome[x] = (int) t; i.genome[x] = (int) u; } } } break; case VectorSpecies.C_INTERMED_RECOMB: { long t,u; long min, max; for (int x = 0; x < len; x++) { do { double alpha = state.random[thread].nextDouble() * (1 + 2*s.lineDistance) - s.lineDistance; double beta = state.random[thread].nextDouble() * (1 + 2*s.lineDistance) - s.lineDistance; min = s.minGene(x); max = s.maxGene(x); t = (long) Math.floor(alpha * genome[x] + (1 - alpha) * i.genome[x] + 0.5); u = (long) Math.floor(beta * i.genome[x] + (1 - beta) * genome[x] + 0.5); } while (t < min || t > max || u < min || u > max); genome[x] = (int) t; i.genome[x] = (int) u; } } break; } } /** Splits the genome into n pieces, according to points, which *must* be sorted. pieces.length must be 1 + points.length */ public void split(int[] points, Object[] pieces) { int point0, point1; point0 = 0; point1 = points[0]; for(int x=0;x=pieces.length-2) point1 = genome.length; else point1 = points[x+1]; } } /** Joins the n pieces and sets the genome to their concatenation.*/ public void join(Object[] pieces) { int sum=0; for(int x=0;x max); return l; } else return min + random.nextInt(max - min + 1); } /** Destructively mutates the individual in some default manner. The default form simply randomizes genes to a uniform distribution from the min and max of the gene values. */ public void defaultMutate(EvolutionState state, int thread) { IntegerVectorSpecies s = (IntegerVectorSpecies) species; for(int x = 0; x < genome.length; x++) if (state.random[thread].nextBoolean(s.mutationProbability(x))) { int old = genome[x]; for(int retries = 0; retries < s.duplicateRetries(x) + 1; retries++) { switch(s.mutationType(x)) { case IntegerVectorSpecies.C_RESET_MUTATION: genome[x] = randomValueFromClosedInterval((int)s.minGene(x), (int)s.maxGene(x), state.random[thread]); break; case IntegerVectorSpecies.C_RANDOM_WALK_MUTATION: int min = (int)s.minGene(x); int max = (int)s.maxGene(x); if (!s.mutationIsBounded(x)) { // okay, technically these are still bounds, but we can't go beyond this without weird things happening max = Integer.MAX_VALUE; min = Integer.MIN_VALUE; } do { int n = (int)(state.random[thread].nextBoolean() ? 1 : -1); int g = genome[x]; if ((n == 1 && g < max) || (n == -1 && g > min)) genome[x] = g + n; else if ((n == -1 && g < max) || (n == 1 && g > min)) genome[x] = g - n; } while (state.random[thread].nextBoolean(s.randomWalkProbability(x))); break; default: state.output.fatal("In IntegerVectorIndividual.defaultMutate, default case occurred when it shouldn't have"); break; } if (genome[x] != old) break; // else genome[x] = old; // try again } } } /** Initializes the individual by randomly choosing Integers uniformly from mingene to maxgene. */ // notice that we bump to longs to avoid overflow errors public void reset(EvolutionState state, int thread) { IntegerVectorSpecies s = (IntegerVectorSpecies) species; for(int x=0;x>> 31 ); for(int x=0;x>> 31 ) ^ genome[x]; return hash; } public String genotypeToStringForHumans() { StringBuilder s = new StringBuilder(); for( int i = 0 ; i < genome.length ; i++ ) { if (i > 0) s.append(" "); s.append(genome[i]); } return s.toString(); } public String genotypeToString() { StringBuilder s = new StringBuilder(); s.append( Code.encode( genome.length ) ); for( int i = 0 ; i < genome.length ; i++ ) s.append( Code.encode( genome[i] ) ); return s.toString(); } protected void parseGenotype(final EvolutionState state, final LineNumberReader reader) throws IOException { // read in the next line. The first item is the number of genes String s = reader.readLine(); DecodeReturn d = new DecodeReturn(s); Code.decode( d ); // of course, even if it *is* an integer, we can't tell if it's a gene or a genome count, argh... if (d.type != DecodeReturn.T_INTEGER) // uh oh state.output.fatal("Individual with genome:\n" + s + "\n... does not have an integer at the beginning indicating the genome count."); int lll = (int)(d.l); genome = new int[ lll ]; // read in the genes for( int i = 0 ; i < genome.length ; i++ ) { Code.decode( d ); genome[i] = (int)(d.l); } } public boolean equals(Object ind) { if (ind == null) return false; if (!(this.getClass().equals(ind.getClass()))) return false; // SimpleRuleIndividuals are special. IntegerVectorIndividual i = (IntegerVectorIndividual)ind; if( genome.length != i.genome.length ) return false; for( int j = 0 ; j < genome.length ; j++ ) if( genome[j] != i.genome[j] ) return false; return true; } public Object getGenome() { return genome; } public void setGenome(Object gen) { genome = (int[]) gen; } public int genomeLength() { return genome.length; } public void writeGenotype(final EvolutionState state, final DataOutput dataOutput) throws IOException { dataOutput.writeInt(genome.length); for(int x=0;x maxGene) genome[i] = maxGene; } } } public void setGenomeLength(int len) { int[] newGenome = new int[len]; System.arraycopy(genome, 0, newGenome, 0, genome.length < newGenome.length ? genome.length : newGenome.length); genome = newGenome; } /** Returns true if each gene value is within is specified [min,max] range. */ public boolean isInRange() { IntegerVectorSpecies _species = (IntegerVectorSpecies)species; for (int i = 0; i < genomeLength(); i++) if (genome[i] < _species.minGene(i) || genome[i] > _species.maxGene(i)) return false; return true; } public double distanceTo(Individual otherInd) { if (!(otherInd instanceof IntegerVectorIndividual)) return super.distanceTo(otherInd); // will return infinity! IntegerVectorIndividual other = (IntegerVectorIndividual) otherInd; int[] otherGenome = other.genome; double sumSquaredDistance =0.0; for(int i=0; i < other.genomeLength(); i++) { long dist = this.genome[i] - (long)otherGenome[i]; sumSquaredDistance += dist*dist; } return StrictMath.sqrt(sumSquaredDistance); } }

Ads help maintain this website.