Click here to Skip to main content
15,896,063 members
Articles / Desktop Programming / MFC

Genetic Algorithm Library

Rate me:
Please Sign up or sign in to vote.
4.93/5 (175 votes)
7 Apr 2012GPL358 min read 439.6K   34.7K   555  
A framework for genetic algorithms

/*! \file Chromosome.h
    \brief This file contains declaration of interfaces and classes needed to implement behavior and representations chromosomes.
*/

/*
 * 
 * website: http://www.coolsoft-sd.com/
 * contact: support@coolsoft-sd.com
 *
 */

/*
 * Genetic Algorithm Library
 * Copyright (C) 2007-2008 Coolsoft Software Development
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#ifndef __GA_CHROMOSOME_H__
#define __GA_CHROMOSOME_H__

#include "Platform.h"
#include "SmartPtr.h"
#include "Operation.h"
#include "SortedGroupType.h"

namespace Population
{
	class GaPopulation;
} // Population

using namespace Common;
using namespace Population;

/// <summary>Contatins interfaces, classes and datatypes needed to implement behavior and representations chromosomes and genetic operations.</summary>
namespace Chromosome
{

	/// <summary>This class is base class for all chromosomes' parameters.
	/// Built-in genetic operations (crossover, mutation, fitness function and comparator) share their parameters with chromosomes parameters.
	///
	/// This class has no built-in synchronizator, so <c>LOCK_OBJECT</c> and <c>LOCK_THIS_OBJECT</c> macros cannot be used with instances of this class.
	/// No public or private methods are thread-safe.</summary>
	class GaChromosomeParams : public GaParameters
	{

	protected:

		/// <summary>Mutation probability in interval (0, 1) of mutation operation being performed during coupling of selected parents.</summary>
		float _mutationProbability;

		/// <summary>Maximal number of affected values in chromosome�s code by mutation operation.</summary>
		int _mutationSize;

		/// <summary>This flag if set, instructs that only mutations which lead to improvement of fitness value should be accepted. If it isn't
		/// set, then all mutation should be accepted.</summary>
		bool _improvingOnlyMutations;

		/// <summary>probability in interval (0, 1) of crossover operation being performed during coupling of selected parents.</summary>
		float _crossoverProbability;

		/// <summary>Number of crossover points between two parents when crossover operation is performed.</summary>
		int _numberOfCrossoverPoints;

	public:

		/// <summary>This constructor initializes parameters with user-defined values.</summary>
		/// <param name="mutationProbability">mutation probability in interval (0, 1).</param>
		/// <param name="mutationSize">maximal number of affected values in chromosome's code by mutation operation.</param>
		/// <param name="improvingOnlyMutations">state of improving only mutation flag.</param>
		/// <param name="crossoverProbability">crossover probability in interval (0, 1).</param>
		/// <param name="numberOfCrossoverPoints">number of crossover points.</param>
		GaChromosomeParams(float mutationProbability,
			int mutationSize,
			bool improvingOnlyMutations,
			float crossoverProbability,
			int numberOfCrossoverPoints) : _mutationProbability(mutationProbability),
			_mutationSize(mutationSize),
			_improvingOnlyMutations(improvingOnlyMutations),
			_crossoverProbability(crossoverProbability),
			_numberOfCrossoverPoints(numberOfCrossoverPoints) { }

		/// <summary>This constructor initializes parameters with default values.
		/// <br>1. mutation probability: 3%
		/// <br>2. mutation size: 1 (only one value is mutated)
		/// <br>3. only improving mutations are accepted: yes
		/// <br>4. crossover probability: 80%
		/// <br>5. number of crossover points: 1
		/// </summary>
		GaChromosomeParams() : _mutationProbability(0.03f),
			_mutationSize(1),
			_improvingOnlyMutations(true),
			_crossoverProbability(0.8f),
			_numberOfCrossoverPoints(1) { }

		/// <summary>More details are given in specification of <see cref="GaParameters::Clone" /> method.
		///
		/// This method is not thread-safe.</summary>
		virtual GaParameters* GACALL Clone() const { return new GaChromosomeParams( *this ); }

		/// <summary>SetMutationProbability method sets probability of mutation operation being performed during coupling of selected parents.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="probability">new probability of mutation operation. Value is in interval (0, 1).</param>
		inline void GACALL SetMutationProbability(float probability) { _mutationProbability = probability; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns probability of mutation operation being performed during coupling of selected parents.</returns>
		inline float GACALL GetMutationProbability() const { return _mutationProbability; }

		/// <summary><c>SetMutationSize</c> method sets maximal number of affected values in chromosome's code by mutation operation. 
		///
		/// This method is not thread-safe.</summary>
		/// <param name="size">maximal number of affected values in chromosome's code.</param>
		inline void GACALL SetMutationSize(int size) { _mutationSize = size; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns maximal number of affected values in chromosome's code by mutation operation. </returns>
		inline int GetMutationSize() const { return _mutationSize; }

		/// <summary><c>SetImprovingMutationsFlag</c> method sets improving-mutation flag.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="improvingOnly">if this parameter is set to <c>true</c>, then only the mutations which lead to improvement of fitness value
		/// should be accepted. If this parameter is set to <c>false</c>, all mutations are accepted.</param>
		inline void GACALL SetImprovingMutationsFlag(bool improvingOnly) { _improvingOnlyMutations	= improvingOnly; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns <c>true</c> if only the mutations which lead to improvement of fitness value should be accepted.
		/// If all mutation should be accepted, then this method return <c>false</c>.</returns>
		inline bool GACALL GetImprovingMutationsFlag() const { return _improvingOnlyMutations; }

		/// <summary> <c>SetCrossoverProbability</c> method sets probability of crossover operation being performed during coupling of selected parents.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="probability">new probability of crossover operation. Value is in interval (0, 1).</param>
		inline void GACALL SetCrossoverProbability(float probability) { _crossoverProbability = probability; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns probability of crossover operation being performed during coupling of selected parents.</returns>
		inline float GACALL GetCrossoverProbability() const { return _crossoverProbability; }

		/// <summary><c>SetNumberOfCrossoverPoints</c> method sets number of crossover points. 
		///
		/// This method is not thread-safe.</summary>
		/// <param name="numberOfPoints">new number of crossover points.</param>
		inline void GACALL SetNumberOfCrossoverPoints(int numberOfPoints) { _numberOfCrossoverPoints = numberOfPoints; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns number of crossover points.</returns>
		inline int GACALL GetNumberOfCrossoverPoints() const { return _numberOfCrossoverPoints; }

	};// END CLASS DEFINITION GaChromosomeParams

	class GaChromosome;

	/// <summary><c>GaChromosomePtr</c> type is instance of <see cref="GaSmartPtr" /> template class and represents smart pointer to a chromosome.
	/// Detailed description can be found in specification of <see cref="GaSmartPtr" /> template class.</summary>
	typedef GaSmartPtr<GaChromosome> GaChromosomePtr;

	/// <summary><c>GaChromosomeConstPtr</c> type is instance of <see cref="GaSmartPtr" /> template class and represents smart pointer to a constant chromosome.
	/// Detailed description can be found in specification of <see cref="GaSmartPtr" /> template class.</summary>
	typedef GaSmartPtr<const GaChromosome> GaChromosomeConstPtr;

	/// <summary><c>GaChromosome</c> is interface for all chromosomes types in the library. Algorithms, populations and genetic operations assume
	/// that all chromosomes obey this interface. Genetic operations over chromosomes (crossover, mutation, fitness function) may require
	/// additional interfaces to be implemented, but all other built-in parts of the library don't have additional assumptions.</summary>
	class GaChromosome
	{

	public:

		/// <summary>Because this is base class, virtual destructor must be defined in order to enable calling of right destructor
		/// (destructor of inheriting class).</summary>
		virtual ~GaChromosome() { };

		/// <summary>This method performs crossover operation with two parents (<c>this</c> and <c>secondParent</c>) and produce offspring.</summary>
		/// <param name="secondParent">smart pointer to second parent.</param>
		/// <returns>Method returns smart pointer to newly created offspring.</returns>
		virtual GaChromosomePtr GACALL Crossover(GaChromosomePtr secondParent) const=0;

		/// <summary>This method performs mutation over <c>this</c> chromosome.</summary>
		virtual void GACALL Mutation()=0;

		/// <summary>This method produces copy of chromosome. It can create exact copy or it can create chromosome with new code,
		/// but with exact setup (parameters, operations, etc).</summary>
		/// <param name="setupOnly">it this parameter is set to <c>true</c> only the setup of the chromosome is copied into new one,
		/// and new chromosome code is created, otherwise the whole chromosome is copied (code and setup).</param>
		/// <returns>Method returns smart pointer to newly created chromosome.</returns>
		virtual GaChromosomePtr GACALL MakeCopy(bool setupOnly) const=0;

		/// <summary>This method creates new chromosome with exact setup (parameters, operations, etc) of this chromosome.</summary>
		/// <returns>Method returns smart pointer to newly created chromosome.</returns>
		virtual GaChromosomePtr GACALL MakeNewFromPrototype() const=0;

		/// <summary>This method returns fitness value of chromosome.</summary>
		/// <returns>Method returns fitness value of chromosome.</returns>
		virtual float GACALL GetFitness() const=0;

		/// <summary>This method compares fitness values of two chromosomes (<c>this</c> and <c>c</c>).
		/// NOTE: Comparison doesn't have to be arithmetical comparison.</summary>
		/// <param name="c">the second chromosome for comparison with <c>this</c>.</param>
		/// <returns>a)	-1 if fitness value of <c>this</c> is lower then value of <c>c</c>.
		/// <br>b)	0 if fitness values of both chromosomes are equal.
		/// <br>c)	1 if fitness value of <c>this</c> is greater then value of <c>c</c>. </returns>
		virtual int GACALL CompareFitnesses(GaChromosomePtr c) const=0;

		/// <summary>This method compares fitness values of two chromosomes (<c>this</c> and <c>c</c>).
		/// NOTE: Comparison doesn't have to be arithmetical comparison.</summary>
		/// <param name="c">the second chromosome for comparison with <c>this</c>.</param>
		/// <returns>a)	-1 if fitness value of <c>this</c> is lower then value of <c>c</c>.
		/// <br>b)	0 if fitness values of both chromosomes are equal.
		/// <br>c)	1 if fitness value of <c>this</c> is greater then value of <c>c</c>. </returns>
		virtual int GACALL CompareFitnesses(float c) const=0;

		/// <summary>This method recalculates fitness value of the chromosome and stores it.</summary>
		virtual void GACALL RefreshFitness()=0;

		/// <summary>This method returns reference of chromosome's parameters.</summary>
		/// <returns>Method returns reference of chromosome's parameters.</returns>
		virtual const GaChromosomeParams& GACALL GetParameters() const=0;

		/// <summary>This method sets pointer to new parameters of chromosome.</summary>
		/// <param name="p">pointer to new parameters.</param>
		virtual void GACALL SetParameters(GaChromosomeParams* p)=0;

		/// <summary>This method returns size of chromosome.s code.</summary>
		/// <returns>Method returns size of chromosome.s code.</returns>
		virtual int GACALL GetCodeSize() const=0;

		/// <summary>This operator copies setup and chromosome's code from <c>rhs</c>.</summary>
		/// <param name="rhs">reference to chromosome which should be copied.</param>
		/// <returns>Method returns reference to this.</returns>
		virtual GaChromosome& GACALL operator =(const GaChromosome& rhs)=0;

		/// <summary>This operator compares chromosomes' codes.</summary>
		/// <param name="c">reference to chromosome which is compared to <c>this</c> chromosome.</param>
		/// <returns>Operator returns <c>true</c> if the chromosomes are equal.</returns>
		virtual bool GACALL operator ==(const GaChromosome& c) const=0;

		/// <summary>This operator compares chromosomes' codes.</summary>
		/// <param name="c">reference to chromosome which is compared to <c>this</c> chromosome.</param>
		/// <returns>Operator returns <c>true</c> if the chromosomes are not equal.</returns>
		virtual bool GACALL operator !=(const GaChromosome& c) const=0;

	protected:

		/// <summary>This method calculates chromosome's fitness value, but it doesn't store it.</summary>
		/// <returns>Method returns calculated fitness value.</returns>
		virtual float GACALL CalculateFitness() const=0;

	};// END CLASS DEFINITION GaChromosome

	class GaFitnessComparator;

	/// <summary>This class wraps chromosome class and represents it in population. To reduce memory usage and improve performance
	/// same chromosome can be placed in multiple populations, but some chromosome's values has different values for separate populations.
	/// All values which are specific to the population are extracted from chromosome class to this class. Same object of <c>GaScaledChromosome</c>
	/// cannot be located in multiple populations.
	///
	/// This class has no built-in synchronizator, so <c>LOCK_OBJECT</c> and <c>LOCK_THIS_OBJECT</c> macros cannot be used with instances of this class.
	/// No public or private methods are thread-safe.</summary>
	class GaScaledChromosome
	{
		DEFINE_SYNC_CLASS

	private:

		/// <summary>Scaled (transformed) fitness value of the chromosome.</summary>
		float _scaledFitness;

		/// <summary>Pointer to population in which the chromosome is located.</summary>
		GaPopulation* _population;

		/// <summary>Smart pointer to chromosome which is bound to population with this object.</summary>
		GaChromosomePtr _chromosome;

		/// <summary>Flags od memberships in sorted groups of population.</summary>
		GaSortedGroupType _groups;

		/// <summary>Index of chromosome in population.</summary>
		int _index;

	public:

		/// <summary>This constructor fully initializes binding object (chromosome, population and index).</summary>
		/// <param name="chromosome">smart pointer to bound chromosome.</param>
		/// <param name="population">pointer to population to which chromosome is bound.</param>
		/// <param name="index">index of chromosome in population.</param>
		GaScaledChromosome(GaChromosomePtr chromosome,
			GaPopulation* population,
			int index);

		/// <summary>This constructor only specifies binding population.</summary>
		/// <param name="population">pointer to population to which chromosome is bound.</param>
		GaScaledChromosome(GaPopulation* population);

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns smart pointer to bound chromosome. Or <c>NULL</c> pointer if object doesn't bind chromosome.</returns>
		inline GaChromosomePtr GACALL GetChromosome() const { return _chromosome; }

		/// <summary><c>SetChromosome</c> sets pointer to bound chromosome.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="chromosome">smart pointer to bound chromosome.</param>
		inline void GACALL SetChromosome(GaChromosomePtr chromosome)
		{
			_chromosome = chromosome;
			Rescale();
		}

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns scaled (transformed) fitness value of bound chromosome.</returns>
		inline float GACALL GetScaledFitness() const { return _scaledFitness; }

		/// <summary><c>SetScaledFitness</c> method sets scaled (transformed) value of bound chromosome.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="fitness">new fitness value.</param>
		inline void GACALL SetScaledFitness(float fitness) { _scaledFitness = fitness; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns fitness value (scaled or original value) which is used for sorting and comparison of chromosomes in population.</returns>
		GAL_API
		float GACALL GetFitnessForComparison() const;

		/// <summary><c>Rescale</c> method recalculates scaled (transformed) fitness value of chromosome.</summary>
		GAL_API
		void GACALL Rescale();

		/// <summary>This method compares fitness values of two chromosomes (<c>this</c> and <c>c</c>).
		/// Which fitness value (scaled or original) is going to be used depends on flag set in population to which chromosomes are bound.
		/// NOTE: Comparison doesn't have to be arithmetical comparison.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="c">second chromosome for comparison with <c>this</c>.</param>
		/// <returns>a) -1 if fitness value of <c>this</c> is lower then value of <c>c</c>.
		/// <br>b) 0 if fitness values of both chromosomes are equal.
		/// <br>c) 1 if fitness value of <c>this</c> is greater then value of <c>c</c>. </returns>
		inline int GACALL CompareFitnesses(const GaScaledChromosome& c) const { return CompareFitnesses( c.GetFitnessForComparison() ); }

		/// <summary>This method compares fitness values of two chromosomes (<c>this</c> and <c>c</c>).
		/// Which fitness value (scaled or original) is going to be used depends on flag set in population to which chromosomes are bound.
		/// NOTE: Comparison doesn't have to be arithmetical comparison.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="c">second chromosome for comparison with <c>this</c>.</param>
		/// <returns>a) -1 if fitness value of <c>this</c> is lower then value of <c>c</c>.
		/// <br>b) 0 if fitness values of both chromosomes are equal.
		/// <br>c) 1 if fitness value of <c>this</c> is greater then value of <c>c</c>. </returns>
		GAL_API
		int GACALL CompareFitnesses(float c) const;

		/// <summary><c>ClearGroupFlag</c> method clears chromosome's membership flag for specified sorted group of population.
		///
		/// <param name="groups">flags of sorted groups that will be set.</param>
		inline void GACALL ClearGroupFlags(GaSortedGroupType groups) { _groups = (GaSortedGroupType)( _groups & ~groups ); }

		/// <summary><c>SetGroupFlag</c> method sets chromosome's membership flag for specified sorted group of population.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="groups">flags of sorted groups that will be set.</param>
		inline void GACALL SetGroupFlags(GaSortedGroupType groups) { _groups = (GaSortedGroupType)( _groups | groups ); }

		/// <summary>Method returns state of desired membership flag(s).
		///
		/// This method is not thread-safe.</summary>
		/// <param name="groups">desired flags of sorted groups which state is queried. Flags are cmbined with operator |.</param>
		/// <param name="all">parameter tells method how the states of flag are combined into result. It this parameter is set to <c>true</c>,
		/// method returns <c>true</c> only if all flags is set, otherwise if this parameter is set to <c>false</c>,
		/// method returns <c>true</c> if any of flags is set.</param>
		/// <returns>It returns <c>true</c> if any of desired flags is set and all parameter is set to <c>false</c>.
		/// If all parameter is set to <c>true</c>, method returns <c>true</c> only if all desired flags are set.</returns>
		inline bool GACALL GetGroupFlag(GaSortedGroupType groups,
			bool all = false) { return all ? ( _groups & groups ) == groups : ( _groups & groups ) != 0; }

		/// <summary><c>SetGroups</c> sets all flags of sorted group membership.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="groups">new values of flags of sorted groups membership.</param>
		inline void GACALL SetGroups(GaSortedGroupType groups) { _groups = groups; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns all values of flags of sorted group membership.</returns>
		inline GaSortedGroupType GACALL GetGroups() const { return _groups; }

		/// <summary><c>SetIndex</c> method sets index of bound chromosome in population.</summary>
		/// <param name="index">new index of bound chromosome.</param>
		GAL_API
		void GACALL SetIndex(int index);

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns index of bound chromosome in population.</returns>
		inline int GACALL GetIndex() const { return _index; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns reference to a population to which chromosome is bound.</returns>
		inline GaPopulation& GACALL GetPopulation() const { return *_population; }

		/// <summary>This operator is not thread-safe.</summary>
		/// <returns>Operator returns smart pointer to bound chromosome. Or <c>NULL</c> pointer if object isn't bound to chromosome.</returns>
		inline GACALL operator GaChromosomePtr() const { return _chromosome; }

		/// <summary>This operator is not thread-safe.</summary>
		/// <returns>Operator returns index of bound chromosome in population.</returns>
		inline GACALL operator float() const { return _scaledFitness; }

	};// END CLASS DEFINITION GaScaledChromosome

	class GaDefaultChromosome;

	/// <summary>This class represent base for chromosome's configuration block (CCB). CCB stores entire setup of chromosome.
	/// <c>GaChromosomeParamsBlock</c> class stores only pointer to chromosomes' parameters.
	///
	/// This class has no built-in synchronizator, so <c>LOCK_OBJECT</c> and <c>LOCK_THIS_OBJECT</c> macros cannot be used with instances of this class.
	/// No public or private methods are thread-safe.</summary>
	class GaChromosomeParamsBlock
	{
		friend class GaDefaultChromosome;

	protected:

		/// <summary>Pointer to chromosomes' parameters.</summary>
		GaChromosomeParams* _parameters;

	public:

		/// <summary>This constructor initializes CCB with pointer to chromosomes' parameters.</summary>
		/// <param name="parameters">pointer to chromosomes' parameters.</param>
		GaChromosomeParamsBlock(GaChromosomeParams* parameters) : _parameters(parameters) { }

		/// <summary>This is copy constructor. The constructor doesn't create copy of parameters' object,
		/// it only copies pointer to chromosomes' parameters.</summary>
		/// <param name="rhs">reference to CCB which is copied.</param>
		GaChromosomeParamsBlock(const GaChromosomeParamsBlock& rhs) : _parameters(rhs._parameters) { }

		/// <summary>This constructor initializes empty CCB.</summary>
		GaChromosomeParamsBlock() : _parameters(NULL) { }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns reference to chromosomes� parameters.</returns>
		inline const GaChromosomeParams& GACALL GetParameters() const { return *_parameters; }

		/// <summary><c>SetParameters</c> method sets pointer to chromosomes' parameters.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="params">pointer to new parameters.</param>
		inline void GACALL SetParameters(GaChromosomeParams* params) { _parameters = params; }

	};// END CLASS DEFINITION GaChromosomeParamsBlock

	// Implements some behavior concerning fitness value, parameters
	// and preaparing chromosome for crossover and mutation operations.
	/// <summary>GaDefaultChromosome class implements some basic feature of chromosome such as management of fitness value, 
	/// CCB and probability of crossover and mutation operations.
	///
	/// This class has no built-in synchronizator, so <c>LOCK_OBJECT</c> and <c>LOCK_THIS_OBJECT</c> macros cannot be used with instances of this class.
	/// No public or private methods are thread-safe.</summary>
	class GaDefaultChromosome : public GaChromosome
	{

	protected:

		/// <summary>Fitness value of the chromosome.</summary>
		float _fitness;

		/// <summary>Pointer to CCB.</summary>
		GaChromosomeParamsBlock* _configBlock;

	public:

		/// <summary>This constructor initializes chromsome with CCB.</summary>
		/// <param name="configBlock">pointer to CCB.</param>
		GaDefaultChromosome(GaChromosomeParamsBlock* configBlock) : _fitness(0),
			_configBlock(configBlock) { }

		/// <summary>Copy constructor.</summary>
		/// <param name="c">reference to chromosome which is copied.</param>
		/// <param name="setupOnly">if this parameter is <c>true</c>, only pointer to CCB is copied. If this parameter is <c>false</c>,
		/// chromosome's data and CCB is copied. </param>
		GaDefaultChromosome(const GaDefaultChromosome& c,
			bool setupOnly) : _configBlock(c._configBlock)
		{
			if( !setupOnly )
				_fitness = c._fitness;
		}

		/// <summary>This method handles probability of mutation and provides framework for improving-only mutations.
		/// It decides if mutation is going to be preformed and if it is going to be accepted. If improving-only flag is set,
		/// the method calls <see cref="PreapareForMutation" /> method, then <see cref="PerformeMutation" /> is called,
		/// after the mutation is performed it checks (only if improving-only flag is set) if the mutation produced chromosome with better fitness,
		/// if that is the case <see cref="AcceptMutation" /> is called, otherwise <see cref="RejectMutation" /> is called.
		///
		/// This method is not thread-safe.</summary>
		GAL_API
		virtual void GACALL Mutation();

		/// <summary>This method handles probability of crossover. It decides if crossover is going to be preformed.
		/// If crossover is going to be performed this method calls <see cref="PerformeCrossover" />.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="secondParent">smart pointer to second parent.</param>
		/// <returns>Method returns smart pointer to newly created offspring.</returns>
		GAL_API
		virtual GaChromosomePtr GACALL Crossover(GaChromosomePtr secondParent) const;

		/// <summary>This method is not-thread safe.</summary>
		/// <returns>Method returns fitness value of chromosome.</returns>
		virtual float GACALL GetFitness() const { return _fitness; }

		/// <summary>This method only extracts fitness value from <c>c</c>, and delegate responsibility to <see cref="ComapreFitnesses(float)" /> method.
		/// More details are given in specification of <see cref="GaChromosome::CompareFitnesses" /> of.
		///
		/// This method is not thread-safe.</summary>
		virtual int GACALL CompareFitnesses(GaChromosomePtr c) const { return CompareFitnesses( c->GetFitness() ); }

		/// <summary>More details are given in specification of <see cref="GaChromosome::CompareFitnesses" />.
		///
		/// This method is not thread-safe.</summary>
		virtual int GACALL CompareFitnesses(float c) const=0;

		/// <summary><c>RefreshFitness</c> method recalculates fitness value of the chromosome and stores it.
		/// 
		/// This method is not thread safe.</summary>
		virtual void GACALL RefreshFitness() { _fitness = CalculateFitness(); }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns reference of chromosome's parameters.</returns>
		virtual const GaChromosomeParams& GACALL GetParameters() const { return *_configBlock->_parameters; }

		/// <summary><c>SetParameters</c> method sets pointer to new parameters of chromosome.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="p">pointer to new parameters.</param>
		virtual void GACALL SetParameters(GaChromosomeParams* p) { _configBlock->_parameters = p; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>This method returns reference to CCB.</returns>
		virtual const GaChromosomeParamsBlock& GACALL GetConfigBlock() const { return *_configBlock; }

		/// <summary><c>SetConfigBlock</c> method sets pointer to new CCB.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="block">pointer to new CCB.</param>
		virtual void GACALL SetConfigBlock(GaChromosomeParamsBlock* block) { _configBlock = block; }

		/// <summary><c>operator =</c> copies setup and chromosome's code from <c>rhs</c>.
		///
		/// This operator is not thread-safe.</summary>
		/// <param name="rhs">reference to chromosome which is copied.</param>
		/// <returns>Method returns reference to this.</returns>
		virtual GaChromosome& GACALL operator =(const GaChromosome& rhs)
		{
			// copy data
			_fitness = ( (const GaDefaultChromosome&)rhs )._fitness;
			_configBlock = ( (const GaDefaultChromosome&)rhs )._configBlock;

			return *this;
		}

		/// <summary>More details are given in specification of <see cref="GaChromosome::operator ==" />.
		///
		/// This method is not thread-safe.</summary>
		virtual bool GACALL operator !=(const GaChromosome& c) const { return !( *this == c ); }

	protected:

		/// <summary>It is called when mutation should be performed over chromosome.</summary>
		virtual void GACALL PerformMutation()=0;

		/// <summary>. It is called when crossover should be performed over two chromosomes to produce offspring.</summary>
		/// <param name="secondParent">smart pointer to second parent.</param>
		/// <returns>Method returns smart pointer to newly created offspring.</returns>
		virtual GaChromosomePtr GACALL PerformCrossover(GaChromosomePtr secondParent) const=0;

		/// <summary>This method called before performing mutation if improving-only mutation flag is set. It should save chromosome's code
		/// so it can be restored if mutation produce chromosome with lower fitness value.</summary>
		virtual void GACALL PreapareForMutation()=0;

		/// <summary>This method is called after mutation is performed if improving-only mutation flag is set and mutation improved fitness value.
		/// The method can delete backed up chromosome's code which was made by <see cref="PreapareForMutation" /> method.</summary>
		virtual void GACALL AcceptMutation()=0;

		/// <summary>This method is called after mutation is performed if improving-only mutation flag is set and mutation degraded fitness value.
		/// The method restores old chromosome's code which was backed up with <see cref="PreapareForMutation" /> method.</summary>
		virtual void GACALL RejectMutation()=0;

	};// END CLASS DEFINITION GaDefaultChromosome

	class GaCrossoverOperation;
	class GaMutationOperation;
	class GaFitnessOperation;
	class GaDynamicOperationChromosome;

	/// <summary>This class is CCB for chromosomes which use extern genetic operations. This CCB stores pointer to those operations.
	///
	/// This class has no built-in synchronizator, so <c>LOCK_OBJECT</c> and <c>LOCK_THIS_OBJECT</c> macros cannot be used with instances of this class.
	/// No public or private methods are thread-safe.</summary>
	class GaChromosomeOperationsBlock : public GaChromosomeParamsBlock
	{
		friend class GaDynamicOperationChromosome;

	protected:

		/// <summary>Pointer to extern fitness operation.</summary>
		GaFitnessOperation* _fitnessOperation;

		/// <summary>Pointer to extern fitness comparator.</summary>
		GaFitnessComparator* _fitnessComparator;

		/// <summary>Pointer to extern mutation operation.</summary>
		GaMutationOperation* _mutationOperation;

		/// <summary>Pointer to extern crossover operation.</summary>
		GaCrossoverOperation* _crossoverOperation;

	public:

		/// <summary>This constructor initializes CCB with pointer to chromosomes' parameters and extern genetic operations.</summary>
		/// <param name="crossoverOperation">pointer to extern crossover operation.</param>
		/// <param name="mutationOperation">pointer to extern mutation operation.</param>
		/// <param name="fitnessOperation">pointer to extern fitness operation.</param>
		/// <param name="fitnessComparator">pointer to extern fitness comparator.</param>
		/// <param name="parameters">pointer to chromosomes� parameters.</param>
		GaChromosomeOperationsBlock(GaCrossoverOperation* crossoverOperation,
			GaMutationOperation* mutationOperation,
			GaFitnessOperation* fitnessOperation,
			GaFitnessComparator* fitnessComparator,
			GaChromosomeParams* parameters) : GaChromosomeParamsBlock(parameters),
			_crossoverOperation(crossoverOperation),
			_mutationOperation(mutationOperation),
			_fitnessOperation(fitnessOperation),
			_fitnessComparator(fitnessComparator) { }

		/// <summary>This is copy constructor. The constructor doesn't create copy of parameters' and operations' objects, 
		/// it only copies pointer to chromosomes' parameters and operations.</summary>
		/// <param name="rhs">reference to CCB which is copied.</param>
		GaChromosomeOperationsBlock(const GaChromosomeOperationsBlock& rhs) : GaChromosomeParamsBlock(rhs),
			_crossoverOperation(rhs._crossoverOperation),
			_mutationOperation(rhs._mutationOperation),
			_fitnessOperation(rhs._fitnessOperation),
			_fitnessComparator(rhs._fitnessComparator) { }

		/// <summary>This constructor initializes empty CCB.</summary>
		GaChromosomeOperationsBlock() : _crossoverOperation(NULL),
			_mutationOperation(NULL),
			_fitnessOperation(NULL),
			_fitnessComparator(NULL) { }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns reference to extern crossover operation.</returns>
		inline const GaCrossoverOperation& GACALL GetCrossoverOperation() const { return *_crossoverOperation; }

		/// <summary><c>SetCrossoverOperation</c> sets pointer to extern crossover operation.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="operation"></param>
		inline void GACALL SetCrossoverOperation(GaCrossoverOperation* operation) { _crossoverOperation = operation; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns reference to extern mutation operation.</returns>
		inline const GaMutationOperation& GACALL GetMutationOperation() const { return *_mutationOperation; }

		/// <summary><c>SetMutationOperation</c> sets pointer to extern mutation operation.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="operation">pointer to extern mutation operation.</param>
		inline void GACALL SetMutationOperation(GaMutationOperation* operation) { _mutationOperation = operation; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns reference to extern fitness operation.</returns>
		inline const GaFitnessOperation& GACALL GetFitnessOperation() const { return *_fitnessOperation; }

		/// <summary><c>SetFitnessOperation</c> sets pointer to extern fitness operation.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="operation">pointer to extern fitness operation.</param>
		inline void GACALL SetFitnessOperation(GaFitnessOperation* operation) { _fitnessOperation = operation; }

		/// <summary>This method is not thread-safe.</summary>
		/// <returns>Method returns reference to extern fitness comparator.</returns>
		inline const GaFitnessComparator& GACALL GetFitnessComparator() const { return *_fitnessComparator; }

		/// <summary>SetFitnessComparator sets pointer to extern fitness comparator.
		///
		/// This method is not thread-safe.</summary>
		/// <param name="comparator">pointer to extern fitness comparator.</param>
		inline void GACALL SetFitnessComparator(GaFitnessComparator* comparator) { _fitnessComparator = comparator; }

	};// END CLASS DEFINITION GaChromosomeOperationsBlock

	/// <summary>This class should be base for chromosomes which use extern genetic operations.
	///
	/// This class has no built-in synchronizator, so <c>LOCK_OBJECT</c> and <c>LOCK_THIS_OBJECT</c> macros cannot be used with instances of this class.
	/// No public or private methods are thread-safe.</summary>
	class GaDynamicOperationChromosome : public GaDefaultChromosome
	{

	public:

		/// <summary>This constructor initializes chromosome with CCB.</summary>
		/// <param name="configBlock">pointer to CCB.</param>
		GaDynamicOperationChromosome(GaChromosomeOperationsBlock* configBlock) : GaDefaultChromosome( configBlock ) { }

		/// <summary>Copy constructor.</summary>
		/// <param name="c">reference to chromosome which is copied.</param>
		/// <param name="setupOnly">if this parameter is <c>true</c>, only pointer to CCB is copied. If this parameter is <c>false</c>,
		/// chromosome's data and CCB is copied.</param>
		GaDynamicOperationChromosome(const GaDynamicOperationChromosome& c,
			bool setupOnly) : GaDefaultChromosome(c, setupOnly) { }

		// Compares fitnesses of two chromosomes. Returns:
		//  a, -1 if the fitness value of this chromosome is lower then the given value
		//  b.  0 if the fitness values of both chromosomes are equal
		//  c.  1 if the fitness value of this chromosome is greater then the given value
		/// <summary>CompareFitnesses method delegates control to extern fitness comparator specified in CCB. 
		///
		/// For more information see specification of <see cref="GaChromosome::CompareFitnesses" /> method.
		///
		/// This method is not thread-safe.</summary>
		GAL_API
		virtual int GACALL CompareFitnesses(float c) const;

	protected:

		/// <summary><c>PerformCrossover</c> method delegates control to extern crossover operation specified in CCB.
		///
		/// For more information see specification of <see cref="GaDefaultChromosome::PerformCrossover" /> method.
		///
		/// This method is not thread-safe.</summary>
		GAL_API
		virtual GaChromosomePtr GACALL PerformCrossover(GaChromosomePtr secondParent) const;

		/// <summary><c>PerformMutation</c> method delegates control to extern mutation operation specified in CCB.
		///
		/// For more information see specification of <see cref="GaDefaultChromosome::PerformMutation" /> method.
		///
		/// This method is not thread-safe.</summary>
		GAL_API
		virtual void GACALL PerformMutation();
		
		/// <summary><c>CalculateFitness</c> method delegates control to extern fitness operation specified in CCB.
		///
		/// For more information see specification of <see cref="GaDefaultChromosome::CalculateFitness" /> method.
		///
		/// This method is not thread-safe.</summary>
		GAL_API
		virtual float GACALL CalculateFitness() const;

	};// END CLASS DEFINITION GaDynamicOperationChromosome

} // Chromosome

#endif // __GA_CHROMOSOME_H__

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer
Serbia Serbia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions