/*
  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.*;

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

/**
 * LongVectorIndividual is a VectorIndividual whose genome is an array of longs.
 * 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.long-vect-ind * @author Sean Luke * @version 1.0 */ public class LongVectorIndividual extends VectorIndividual { public static final String P_LONGVECTORINDIVIDUAL = "long-vect-ind"; public long[] genome; public Parameter defaultBase() { return VectorDefaults.base().push(P_LONGVECTORINDIVIDUAL); } public Object clone() { LongVectorIndividual myobj = (LongVectorIndividual) (super.clone()); // must clone the genome myobj.genome = (long[])(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("LongVectorIndividual requires an IntegerVectorSpecies", base, def); IntegerVectorSpecies s = (IntegerVectorSpecies) species; genome = new long[s.genomeSize]; } // Because Math.floor only goes within the double integer space long longFloor(double x) { long l = (long) x; // pulls towards zero if (x >= 0) { return l; // NaN will get shunted to 0 apparently } else if (x < Long.MIN_VALUE + 1) // it'll go to Long.MIN_VALUE { return Long.MIN_VALUE; } else if (l == x) // it's exact { return l; } else { return l - 1; } } public void defaultCrossover(EvolutionState state, int thread, VectorIndividual ind) { IntegerVectorSpecies s = (IntegerVectorSpecies) species; LongVectorIndividual i = (LongVectorIndividual) ind; long 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] = t; i.genome[x] = 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 = longFloor(alpha * genome[x] + (1 - alpha) * i.genome[x] + 0.5); u = longFloor(beta * i.genome[x] + (1 - beta) * genome[x] + 0.5); } while (t < min || t > max || u < min || u > max); genome[x] = t; i.genome[x] = 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.nextLong(max - min + 1L); } /** Returns a random value from between min and max inclusive. This method handles overflows that complicate this computation. Does NOT check that min is less than or equal to max. You must check this yourself. */ public short randomValueFromClosedInterval(short min, short max, MersenneTwisterFast random) { if (max - min < 0) // we had an overflow { short l = 0; do l = (short)random.nextInt(); while(l < min || l > max); return l; } else return (short)(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))) { long 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((long)s.minGene(x), (long)s.maxGene(x), state.random[thread]); break; case IntegerVectorSpecies.C_RANDOM_WALK_MUTATION: long min = (long)s.minGene(x); long max = (long)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 = Long.MAX_VALUE; min = Long.MIN_VALUE; } do { long n = (state.random[thread].nextBoolean() ? 1L : -1L); long g = genome[x]; if ((n == 1L && g < max) || (n == -1L && g > min)) genome[x] = g + n; else if ((n == -1L && g < max) || (n == 1L && g > min)) genome[x] = g - n; } while (state.random[thread].nextBoolean(s.randomWalkProbability(x))); break; default: state.output.fatal("In LongVectorIndividual.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 Longs uniformly from mingene to maxgene. */ public void reset(EvolutionState state, int thread) { IntegerVectorSpecies s = (IntegerVectorSpecies) species; for(int x=0;x>> 31 ); for(int x=0;x>> 31 ) ^ (int)((genome[x] >>> 16) & 0xFFFFFFFF) ^ (int)(genome[x] & 0xFFFF); 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 ); 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 long[ lll ]; // read in the genes for( int i = 0 ; i < genome.length ; i++ ) { Code.decode( d ); genome[i] = d.l; } } public boolean equals(Object ind) { if (ind == null) return false; if (!(this.getClass().equals(ind.getClass()))) return false; // SimpleRuleIndividuals are special. LongVectorIndividual i = (LongVectorIndividual)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 = (long[]) 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) { long[] newGenome = new long[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 LongVectorIndividual)) return super.distanceTo(otherInd); // will return infinity! LongVectorIndividual other = (LongVectorIndividual) otherInd; long[] otherGenome = other.genome; double sumSquaredDistance =0.0; for(int i=0; i < other.genomeLength(); i++) { // can't subtract two longs and expect a long. Must convert to doubles :-( double dist = this.genome[i] - (double)otherGenome[i]; sumSquaredDistance += dist*dist; } return StrictMath.sqrt(sumSquaredDistance); } }

Ads help maintain this website.