/** * Convenience method that returns a new Chromosome instance with its genes values (alleles) * randomized. Note that, if possible, this method will acquire a Chromosome instance from the * active ChromosomePool (if any) and then randomize its gene values before returning it. If a * Chromosome cannot be acquired from the pool, then a new instance will be constructed and its * gene values randomized before returning it. * * @param a_configuration the configuration to use * @return randomly initialized Chromosome * @throws InvalidConfigurationException if the given Configuration instance is invalid * @throws IllegalArgumentException if the given Configuration instance is null * @author Neil Rotstan * @author Klaus Meffert * @since 1.0 */ public static IChromosome randomInitialChromosome(Configuration a_configuration) throws InvalidConfigurationException { // Sanity check: make sure the given configuration isn't null. // ----------------------------------------------------------- if (a_configuration == null) { throw new IllegalArgumentException("Configuration instance must not be null"); } // Lock the configuration settings so that they can't be changed // from now on. // ------------------------------------------------------------- a_configuration.lockSettings(); // First see if we can get a Chromosome instance from the pool. // If we can, we'll randomize its gene values (alleles) and then // return it. // ------------------------------------------------------------- IChromosomePool pool = a_configuration.getChromosomePool(); if (pool != null) { IChromosome randomChromosome = pool.acquireChromosome(); if (randomChromosome != null) { Gene[] genes = randomChromosome.getGenes(); RandomGenerator generator = a_configuration.getRandomGenerator(); for (int i = 0; i < genes.length; i++) { genes[i].setToRandomValue(generator); /** @todo what about Gene's energy? */ } randomChromosome.setFitnessValueDirectly(FitnessFunction.NO_FITNESS_VALUE); return randomChromosome; } } // We weren't able to get a Chromosome from the pool, so we have to // construct a new instance and build it from scratch. // ------------------------------------------------------------------ IChromosome sampleChromosome = a_configuration.getSampleChromosome(); sampleChromosome.setFitnessValue(FitnessFunction.NO_FITNESS_VALUE); Gene[] sampleGenes = sampleChromosome.getGenes(); Gene[] newGenes = new Gene[sampleGenes.length]; RandomGenerator generator = a_configuration.getRandomGenerator(); for (int i = 0; i < newGenes.length; i++) { // We use the newGene() method on each of the genes in the // sample Chromosome to generate our new Gene instances for // the Chromosome we're returning. This guarantees that the // new Genes are setup with all of the correct internal state // for the respective gene position they're going to inhabit. // ----------------------------------------------------------- newGenes[i] = sampleGenes[i].newGene(); // Set the gene's value (allele) to a random value. // ------------------------------------------------ newGenes[i].setToRandomValue(generator); /** @todo what about Gene's energy? */ } // Finally, construct the new chromosome with the new random // genes values and return it. // --------------------------------------------------------- return new Chromosome(a_configuration, newGenes); }
/** * Operate on the given chromosome with the given mutation rate. * * @param a_chrom chromosome to operate * @param a_rate mutation rate * @param a_generator random generator to use (must not be null) * @return mutated chromosome of null if no mutation has occured. * @author Audrius Meskauskas * @author Florian Hafner * @since 3.3.2 */ protected IChromosome operate( final IChromosome a_chrom, final int a_rate, final RandomGenerator a_generator) { IChromosome chromosome = null; // ---------------------------------------- for (int j = m_startOffset; j < a_chrom.size(); j++) { // Ensure probability of 1/currentRate for applying mutation. // ---------------------------------------------------------- if (a_generator.nextInt(a_rate) == 0) { if (chromosome == null) { chromosome = (IChromosome) a_chrom.clone(); // In case monitoring is active, support it. // ----------------------------------------- if (m_monitorActive) { chromosome.setUniqueIDTemplate(a_chrom.getUniqueID(), 1); } } Gene[] genes = chromosome.getGenes(); if (m_range == 0) { m_range = genes.length; } Gene[] mutated = operate(a_generator, j, genes); // setGenes is not required for this operator, but it may // be needed for the derived operators. // ------------------------------------------------------ try { chromosome.setGenes(mutated); } catch (InvalidConfigurationException cex) { throw new Error("Gene type not allowed by constraint checker", cex); } } } return chromosome; }
boolean checkAlleles(IChromosome chrom, int j, int nextInt) { Gene[] newgene = chrom.getGenes(); Integer[] alleles = new Integer[j]; for (int i = 0; i < j; i++) { alleles[i] = (Integer) newgene[i].getAllele(); } if (Arrays.asList(alleles).contains(new Integer(nextInt))) { return true; } return false; }
/** * Marshall a Chromosome instance to an XML Element representation, including its contained Genes * as sub-elements. This may be useful in scenarios where representation as an entire Document is * undesirable, such as when the representation of this Chromosome is to be combined with other * elements in a single Document. * * @param a_subject the chromosome to represent as an XML element * @param a_xmlDocument a Document instance that will be used to create the Element instance. Note * that the element will NOT be added to the document by this method * @return an Element object representing the given Chromosome * @author Neil Rotstan * @since 1.0 * @deprecated use XMLDocumentBuilder instead */ public static Element representChromosomeAsElement( final IChromosome a_subject, final Document a_xmlDocument) { // Start by creating an element for the chromosome and its size // attribute, which represents the number of genes in the chromosome. // ------------------------------------------------------------------ Element chromosomeElement = a_xmlDocument.createElement(CHROMOSOME_TAG); chromosomeElement.setAttribute(SIZE_ATTRIBUTE, Integer.toString(a_subject.size())); // Next create the genes element with its nested gene elements, // which will contain string representations of the alleles. // -------------------------------------------------------------- Element genesElement = representGenesAsElement(a_subject.getGenes(), a_xmlDocument); // Add the new genes element to the chromosome element and then // return the chromosome element. // ------------------------------------------------------------- chromosomeElement.appendChild(genesElement); return chromosomeElement; }
/** * Compares the given Chromosome to this Chromosome. This chromosome is considered to be "less * than" the given chromosome if it has a fewer number of genes or if any of its gene values * (alleles) are less than their corresponding gene values in the other chromosome. * * @param other the Chromosome against which to compare this chromosome * @return a negative number if this chromosome is "less than" the given chromosome, zero if they * are equal to each other, and a positive number if this chromosome is "greater than" the * given chromosome * @author Neil Rotstan * @author Klaus Meffert * @since 1.0 */ public int compareTo(Object other) { // First, if the other Chromosome is null, then this chromosome is // automatically the "greater" Chromosome. // --------------------------------------------------------------- if (other == null) { return 1; } int size = size(); IChromosome otherChromosome = (IChromosome) other; Gene[] otherGenes = otherChromosome.getGenes(); // If the other Chromosome doesn't have the same number of genes, // then whichever has more is the "greater" Chromosome. // -------------------------------------------------------------- if (otherChromosome.size() != size) { return size() - otherChromosome.size(); } // Next, compare the gene values (alleles) for differences. If // one of the genes is not equal, then we return the result of its // comparison. // --------------------------------------------------------------- for (int i = 0; i < size; i++) { int comparison = getGene(i).compareTo(otherGenes[i]); if (comparison != 0) { return comparison; } } // Compare current fitness value. // ------------------------------ if (m_fitnessValue != otherChromosome.getFitnessValueDirectly()) { FitnessEvaluator eval = getConfiguration().getFitnessEvaluator(); if (eval != null) { if (eval.isFitter(m_fitnessValue, otherChromosome.getFitnessValueDirectly())) { return 1; } else { return -1; } } else { // undetermined order, but unequal! // -------------------------------- return -1; } } if (m_compareAppData) { // Compare application data. // ------------------------- if (getApplicationData() == null) { if (otherChromosome.getApplicationData() != null) { return -1; } } else if (otherChromosome.getApplicationData() == null) { return 1; } else { if (getApplicationData() instanceof Comparable) { try { return ((Comparable) getApplicationData()) .compareTo(otherChromosome.getApplicationData()); } catch (ClassCastException cex) { /** @todo improve */ return -1; } } else { return getApplicationData() .getClass() .getName() .compareTo(otherChromosome.getApplicationData().getClass().getName()); } } } // Everything is equal. Return zero. // --------------------------------- return 0; }
/** * Returns a copy of this Chromosome. The returned instance can evolve independently of this * instance. Note that, if possible, this method will first attempt to acquire a Chromosome * instance from the active ChromosomePool (if any) and set its value appropriately before * returning it. If that is not possible, then a new Chromosome instance will be constructed and * its value set appropriately before returning. * * @return copy of this Chromosome * @throws IllegalStateException instead of CloneNotSupportedException * @author Neil Rotstan * @author Klaus Meffert * @since 1.0 */ public synchronized Object clone() { // Before doing anything, make sure that a Configuration object // has been set on this Chromosome. If not, then throw an // IllegalStateException. // ------------------------------------------------------------ if (getConfiguration() == null) { throw new IllegalStateException( "The active Configuration object must be set on this " + "Chromosome prior to invocation of the clone() method."); } IChromosome copy = null; // Now, first see if we can pull a Chromosome from the pool and just // set its gene values (alleles) appropriately. // ------------------------------------------------------------ IChromosomePool pool = getConfiguration().getChromosomePool(); if (pool != null) { copy = pool.acquireChromosome(); if (copy != null) { Gene[] genes = copy.getGenes(); for (int i = 0; i < size(); i++) { genes[i].setAllele(getGene(i).getAllele()); } } } try { if (copy == null) { // We couldn't fetch a Chromosome from the pool, so we need to create // a new one. First we make a copy of each of the Genes. We explicity // use the Gene at each respective gene location (locus) to create the // new Gene that is to occupy that same locus in the new Chromosome. // ------------------------------------------------------------------- int size = size(); if (size > 0) { Gene[] copyOfGenes = new Gene[size]; for (int i = 0; i < copyOfGenes.length; i++) { copyOfGenes[i] = getGene(i).newGene(); Object allele = getGene(i).getAllele(); if (allele != null) { IJGAPFactory factory = getConfiguration().getJGAPFactory(); if (factory != null) { ICloneHandler cloner = factory.getCloneHandlerFor(allele, allele.getClass()); if (cloner != null) { try { allele = cloner.perform(allele, null, this); } catch (Exception ex) { throw new RuntimeException(ex); } } } } copyOfGenes[i].setAllele(allele); } // Now construct a new Chromosome with the copies of the genes and // return it. Also clone the IApplicationData object later on. // --------------------------------------------------------------- if (getClass() == Chromosome.class) { copy = new Chromosome(getConfiguration(), copyOfGenes); } else { copy = (IChromosome) getConfiguration().getSampleChromosome().clone(); copy.setGenes(copyOfGenes); } } else { if (getClass() == Chromosome.class) { copy = new Chromosome(getConfiguration()); } else { copy = (IChromosome) getConfiguration().getSampleChromosome().clone(); } } } copy.setFitnessValue(m_fitnessValue); // Clone constraint checker. // ------------------------- copy.setConstraintChecker(getConstraintChecker()); } catch (InvalidConfigurationException iex) { throw new IllegalStateException(iex.getMessage()); } // Also clone the IApplicationData object. // --------------------------------------- try { copy.setApplicationData(cloneObject(getApplicationData())); } catch (Exception ex) { throw new IllegalStateException(ex.getMessage()); } // Clone multi-objective object if necessary and possible. // ------------------------------------------------------- if (m_multiObjective != null) { if (getClass() == Chromosome.class) { try { ((Chromosome) copy).setMultiObjectives((List) cloneObject(m_multiObjective)); } catch (Exception ex) { throw new IllegalStateException(ex.getMessage()); } } } return copy; }
protected void doCrossover( IChromosome firstMate, IChromosome secondMate, List a_candidateChromosomes, RandomGenerator generator) { Gene[] firstGenes = firstMate.getGenes(); Gene[] secondGenes = secondMate.getGenes(); int locus = generator.nextInt(firstGenes.length); // Swap the genes. // --------------- Gene gene1, gene11; Gene gene2, gene22; Integer firstAllele, firstAllele1; Integer secondAllele, secondAllele1; for (int j = locus; j < firstGenes.length; j++) { gene1 = firstGenes[j]; gene2 = secondGenes[j]; firstAllele = (Integer) gene1.getAllele(); secondAllele = (Integer) gene2.getAllele(); if (payload[firstAllele] != null && payload[secondAllele] != null) { if (!checkAlleles(firstMate, j, secondAllele)) gene1.setAllele(secondAllele); if (!checkAlleles(secondMate, j, firstAllele)) gene2.setAllele(firstAllele); } if (payload[firstAllele] == null && payload[secondAllele] == null) { if (payload[64 + firstAllele].getPair() != payload[64 + secondAllele].getPair()) continue; if (payload[64 + firstAllele].getPair() == 1) { if (!checkAlleles(firstMate, j, secondAllele) && !checkAlleles(secondMate, j, firstAllele)) { if (chkonepair(j) || chktwopair(j + 1)) { System.out.println("Crossover.. something wrong"); } gene11 = firstGenes[j + 1]; firstAllele1 = (Integer) gene11.getAllele(); gene22 = secondGenes[j + 1]; secondAllele1 = (Integer) gene22.getAllele(); if (!checkAlleles(firstMate, j + 1, secondAllele1)) { gene1.setAllele(secondAllele); gene11.setAllele(secondAllele1); } if (!checkAlleles(secondMate, j + 1, firstAllele1)) { gene2.setAllele(firstAllele); gene22.setAllele(firstAllele1); } } } else if (payload[64 + firstAllele].getPair() == 2) { if (!checkAlleles(firstMate, j, secondAllele) && !checkAlleles(secondMate, j, firstAllele)) { gene11 = firstGenes[j - 1]; firstAllele1 = (Integer) gene11.getAllele(); gene22 = secondGenes[j - 1]; secondAllele1 = (Integer) gene22.getAllele(); if (!checkAlleles(firstMate, j - 1, secondAllele1)) { gene1.setAllele(secondAllele); gene11.setAllele(secondAllele1); } if (!checkAlleles(secondMate, j - 1, firstAllele1)) { gene2.setAllele(firstAllele); gene22.setAllele(firstAllele1); } } } else { System.out.println("...Invalid Configuration Exception..."); } } } // Add the modified chromosomes to the candidate pool so that // they'll be considered for natural selection during the next // phase of evolution. // ----------------------------------------------------------- a_candidateChromosomes.add(firstMate); a_candidateChromosomes.add(secondMate); }