001 /* 002 * Copyright 2011 Christian Kumpe http://kumpe.de/christian/java 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package de.kumpe.hadooptimizer.impl; 017 018 import static java.lang.String.*; 019 020 import java.util.ArrayList; 021 import java.util.Collection; 022 023 import org.apache.commons.logging.Log; 024 import org.apache.commons.logging.LogFactory; 025 import org.apache.commons.math.random.RandomGenerator; 026 027 import de.kumpe.hadooptimizer.EvaluationResult; 028 import de.kumpe.hadooptimizer.NeedsRandomGenerator; 029 import de.kumpe.hadooptimizer.Recombiner; 030 031 /** 032 * A {@link Recombiner} which creates the given number of offspring by randomly 033 * selecting and duplicating a parents. 034 * <p> 035 * It does not copy the parents! It only "duplicate" the reference. 036 * 037 * @param <I> 038 * the individual's type 039 * 040 * @author <a href="http://kumpe.de/christian/java">Christian Kumpe</a> 041 */ 042 public final class DuplicatingRecombiner<I> implements Recombiner<I>, 043 NeedsRandomGenerator { 044 private static final long serialVersionUID = 1L; 045 private static final Log log = LogFactory 046 .getLog(DuplicatingRecombiner.class); 047 048 private final int offspring; 049 private RandomGenerator randomGenerator; 050 051 /** 052 * Creates a new {@link DuplicatingRecombiner} which generated the given 053 * number of offspring. 054 * 055 * @param offspring 056 * the number of offspring to create in 057 * {@link #recombine(Collection) recombination} 058 */ 059 public DuplicatingRecombiner(final int offspring) { 060 if (0 >= offspring) { 061 throw new IllegalArgumentException( 062 "offspring must be greater than zero"); 063 } 064 065 if (log.isDebugEnabled()) { 066 log.debug(format( 067 "Constructing new DuplicatingPairingSelector which creates %d offspring.", 068 offspring)); 069 } 070 071 this.offspring = offspring; 072 } 073 074 @Override 075 public void setRandomGenerator(final RandomGenerator randomGenerator) { 076 this.randomGenerator = randomGenerator; 077 } 078 079 public int getOffspring() { 080 return offspring; 081 } 082 083 @Override 084 public Collection<I> recombine( 085 final Collection<EvaluationResult<I>> parentResults) { 086 if (log.isTraceEnabled()) { 087 log.trace(format("Duplicating %d parents to %d offspring.", 088 parentResults.size(), offspring)); 089 } 090 091 final int nrOfParents = parentResults.size(); 092 @SuppressWarnings("unchecked") 093 final EvaluationResult<I>[] parentsAsArray = (EvaluationResult<I>[]) parentResults 094 .toArray(new EvaluationResult<?>[nrOfParents]); 095 final Collection<I> children = new ArrayList<I>(offspring); 096 097 // create offspring children 098 for (int i = 0; i < offspring; i++) { 099 final int selectedParent = randomGenerator.nextInt(nrOfParents); 100 children.add(parentsAsArray[selectedParent].getIndividual()); 101 } 102 103 return children; 104 } 105 }