/* * File: ParallelizedGeneticAlgorithm.java * Authors: Christina Warrender * Company: Sandia National Laboratories * Project: Cognitive Foundry * * Copyright October 08, 2008, Sandia Corporation. * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive * license for use of this work by or on behalf of the U.S. Government. Export * of this program may require a license from the United States Government. * See CopyrightHistory.txt for complete details. * */ package gov.sandia.cognition.learning.algorithm.genetic; import gov.sandia.cognition.algorithm.ParallelAlgorithm; import gov.sandia.cognition.algorithm.ParallelUtil; import gov.sandia.cognition.learning.algorithm.genetic.reproducer.Reproducer; import gov.sandia.cognition.learning.data.SequentialDataMultiPartitioner; import gov.sandia.cognition.learning.function.cost.CostFunction; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.logging.Level; import java.util.logging.Logger; /** * This is a parallel implementation of the genetic algorithm. The * default is to use n-1 available cores/hyperthreads on a machine and spread * the cost function evaluations across these computational units. * * @param <GenomeType> Type of genome used to represent a single element in * the genetic population. For example, a {@code Vector}. * @param <CostParametersType> Type of parameters that the cost function * takes. For example, {@code Collection<InputOutputPairs>}. * @author cewarr */ public class ParallelizedGeneticAlgorithm <CostParametersType, GenomeType> extends GeneticAlgorithm<CostParametersType, GenomeType> implements ParallelAlgorithm { /** * Parallel tasks that evaluate genome fitness */ private ArrayList<Callable<ArrayList<EvaluatedGenome<GenomeType>>>> evaluateTasks; /** * Thread pool used to parallelize the computation */ private transient ThreadPoolExecutor threadPool; /** * Default constructor */ public ParallelizedGeneticAlgorithm() { this( null, null, null, null ); } /** * @param initialPopulation The initial population to start the algorithm * @param reproducer The reproduction method to use. * @param cost The cost function for genomes. * @param threadPool Thread pool to use for parallelization */ public ParallelizedGeneticAlgorithm( Collection<GenomeType> initialPopulation, Reproducer<GenomeType> reproducer, CostFunction<? super GenomeType, ? super CostParametersType> cost, ThreadPoolExecutor threadPool) { super(initialPopulation, reproducer, cost); this.setThreadPool( threadPool ); } /** * @param initialPopulation The initial population to start the algorithm * @param reproducer The reproduction method to use. * @param cost The cost function for genomes. * @param threadPool Thread pool to use for parallelization * @param maxIterations The maximum number of iterations to run. * @param maxIterationsWithoutImprovement The maximum number of iterations * to go without improvement before stopping. */ public ParallelizedGeneticAlgorithm( Collection<GenomeType> initialPopulation, Reproducer<GenomeType> reproducer, CostFunction<? super GenomeType, ? super CostParametersType> cost, ThreadPoolExecutor threadPool, int maxIterations, int maxIterationsWithoutImprovement) { super(initialPopulation, reproducer, cost, maxIterations, maxIterationsWithoutImprovement); this.setThreadPool( threadPool ); } /** * Getter for threadPool * @return * Thread pool used to parallelize the computation */ public ThreadPoolExecutor getThreadPool() { return this.threadPool; } /** * Setter for threadPool * @param threadPool * Thread pool used to parallelize the computation */ public void setThreadPool( ThreadPoolExecutor threadPool ) { this.threadPool = threadPool; } /** * Getter for #threads * @return * #threads */ public int getNumThreads() { return ParallelUtil.getNumThreads( this ); } /** * Creates the evaluation tasks to execute in parallel. * * @param population * The population to create tasks for. */ protected void createEvaluationTasks( Collection<GenomeType> population ) { if( this.getThreadPool() == null ) { this.setThreadPool( ParallelUtil.createThreadPool() ); } int numThreads = this.getNumThreads(); ArrayList<ArrayList<GenomeType>> partitions = SequentialDataMultiPartitioner.create( population, numThreads ); this.evaluateTasks = new ArrayList<Callable<ArrayList<EvaluatedGenome<GenomeType>>>>( numThreads ); for( int i = 0; i < numThreads; i++ ) { this.evaluateTasks.add( new EvaluateGenome( partitions.get( i ) ) ); } } /** * Converts a population of genomes into evaluated genomes. * * @param population The population of genomes to evaluate. * @return A population of evaluated genomes. */ @Override protected ArrayList<EvaluatedGenome<GenomeType>> evaluatePopulation( Collection<GenomeType> population) { if (population == null) return null; // create tasks to evaluate population in parallel this.createEvaluationTasks( population ); // Convert the Genome to an EvaluatedGenome. ArrayList<EvaluatedGenome<GenomeType>> evaluatedPopulation = new ArrayList<EvaluatedGenome<GenomeType>>(population.size()); try { // Execute the evaluations in parallel List<Future<ArrayList<EvaluatedGenome<GenomeType>>>> results = this.getThreadPool().invokeAll( this.evaluateTasks ); for( Future<ArrayList<EvaluatedGenome<GenomeType>>> result : results ) { evaluatedPopulation.addAll( 0, result.get() ); } } catch (Exception ex) { Logger.getLogger( ParallelizedGeneticAlgorithm.class.getName() ).log( Level.SEVERE, null, ex ); } return evaluatedPopulation; } /** * Callable task for the evaluate() method. */ protected class EvaluateGenome implements Callable<ArrayList<EvaluatedGenome<GenomeType>>> { private Collection<GenomeType> population; /** * Creates a new instance of EvaluateGenome * @param population * Population to evaluate */ public EvaluateGenome( ArrayList<GenomeType> population ) { this.population = population; } public ArrayList<EvaluatedGenome<GenomeType>> call() { return ParallelizedGeneticAlgorithm.super.evaluatePopulation(this.population); } } }