#region License Information
/* HeuristicLab
* Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab 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 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab 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 HeuristicLab. If not, see .
*/
#endregion
using System;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Optimization;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence;
namespace HeuristicLab.Encodings.RealVectorEncoding {
///
/// Blend alpha-beta crossover for real vectors (BLX-a-b). Creates a new offspring by selecting a
/// random value from the interval between the two alleles of the parent solutions.
/// The interval is increased in both directions as follows: Into the direction of the 'better'
/// solution by the factor alpha, into the direction of the 'worse' solution by the factor beta.
///
///
/// It is implemented as described in Takahashi, M. and Kita, H. 2001. A crossover operator using independent component analysis for real-coded genetic algorithms Proceedings of the 2001 Congress on Evolutionary Computation, pp. 643-649.
/// The default value for alpha is 0.75, the default value for beta is 0.25.
///
[Item("BlendAlphaBetaCrossover", "The blend alpha beta crossover (BLX-a-b) for real vectors is similar to the blend alpha crossover (BLX-a), but distinguishes between the better and worse of the parents. The interval from which to choose the new offspring can be extended beyond the better parent by specifying a higher alpha value, and beyond the worse parent by specifying a higher beta value. The new offspring is sampled uniformly in the extended range. It is implemented as described in Takahashi, M. and Kita, H. 2001. A crossover operator using independent component analysis for real-coded genetic algorithms Proceedings of the 2001 Congress on Evolutionary Computation, pp. 643-649.")]
[StorableType("9bf6736e-2e38-49ee-a154-87d8f0b2cd7c")]
public class BlendAlphaBetaCrossover : RealVectorCrossover, ISingleObjectiveOperator {
///
/// Whether the problem is a maximization or minimization problem.
///
public ValueLookupParameter MaximizationParameter {
get { return (ValueLookupParameter)Parameters["Maximization"]; }
}
///
/// The quality of the parents.
///
public ScopeTreeLookupParameter QualityParameter {
get { return (ScopeTreeLookupParameter)Parameters["Quality"]; }
}
///
/// The Alpha parameter controls the extension of the range beyond the better parent. The value must be >= 0 and does not depend on Beta.
///
public ValueLookupParameter AlphaParameter {
get { return (ValueLookupParameter)Parameters["Alpha"]; }
}
///
/// The Beta parameter controls the extension of the range beyond the worse parent. The value must be >= 0 and does not depend on Alpha.
///
public ValueLookupParameter BetaParameter {
get { return (ValueLookupParameter)Parameters["Beta"]; }
}
[StorableConstructor]
protected BlendAlphaBetaCrossover(StorableConstructorFlag deserializing) : base(deserializing) { }
protected BlendAlphaBetaCrossover(BlendAlphaBetaCrossover original, Cloner cloner) : base(original, cloner) { }
///
/// Initializes a new instance of with four additional parameters
/// (Maximization, Quality, Alpha and Beta).
///
public BlendAlphaBetaCrossover()
: base() {
Parameters.Add(new ValueLookupParameter("Maximization", "Whether the problem is a maximization problem or not."));
Parameters.Add(new ScopeTreeLookupParameter("Quality", "The quality values of the parents."));
Parameters.Add(new ValueLookupParameter("Alpha", "The Alpha parameter controls the extension of the range beyond the better parent. The value must be >= 0 and does not depend on Beta.", new DoubleValue(0.75)));
Parameters.Add(new ValueLookupParameter("Beta", "The Beta parameter controls the extension of the range beyond the worse parent. The value must be >= 0 and does not depend on Alpha.", new DoubleValue(0.25)));
}
public override IDeepCloneable Clone(Cloner cloner) {
return new BlendAlphaBetaCrossover(this, cloner);
}
///
/// Performs the blend alpha beta crossover (BLX-a-b) on two parent vectors.
///
///
/// Thrown when either:
///
/// - The length of and is not equal.
/// - The parameter is smaller than 0.
/// - The parameter is smaller than 0.
///
///
/// The random number generator to use.
/// The better of the two parents with regard to their fitness.
/// The worse of the two parents with regard to their fitness.
/// The parameter alpha.
/// The parameter beta.
/// The real vector that results from the crossover.
public static RealVector Apply(IRandom random, RealVector betterParent, RealVector worseParent, DoubleValue alpha, DoubleValue beta) {
if (betterParent.Length != worseParent.Length) throw new ArgumentException("BlendAlphaBetaCrossover: The parents' vectors are of different length.", "betterParent");
if (alpha.Value < 0) throw new ArgumentException("BlendAlphaBetaCrossover: Parameter alpha must be greater or equal to 0.", "alpha");
if (beta.Value < 0) throw new ArgumentException("BlendAlphaBetaCrossover: Parameter beta must be greater or equal to 0.", "beta");
int length = betterParent.Length;
double min, max, d;
RealVector result = new RealVector(length);
for (int i = 0; i < length; i++) {
d = Math.Abs(betterParent[i] - worseParent[i]);
if (betterParent[i] <= worseParent[i]) {
min = betterParent[i] - d * alpha.Value;
max = worseParent[i] + d * beta.Value;
} else {
min = worseParent[i] - d * beta.Value;
max = betterParent[i] + d * alpha.Value;
}
result[i] = min + random.NextDouble() * (max - min);
}
return result;
}
///
/// Checks if the number of parents is equal to 2, if all parameters are available and forwards the call to .
///
/// Thrown when the number of parents is not equal to 2.
///
/// Thrown when either:
///
/// - Maximization parameter could not be found.
/// - Quality parameter could not be found or the number of quality values is not equal to the number of parents.
/// - Alpha parameter could not be found.
/// - Beta parameter could not be found.
///
///
/// The random number generator to use.
/// The collection of parents (must be of size 2).
/// The real vector that results from the crossover.
protected override RealVector Cross(IRandom random, ItemArray parents) {
if (parents.Length != 2) throw new ArgumentException("BlendAlphaBetaCrossover: Number of parents is not equal to 2.", "parents");
if (MaximizationParameter.ActualValue == null) throw new InvalidOperationException("BlendAlphaBetaCrossover: Parameter " + MaximizationParameter.ActualName + " could not be found.");
if (QualityParameter.ActualValue == null || QualityParameter.ActualValue.Length != parents.Length) throw new InvalidOperationException("BlendAlphaBetaCrossover: Parameter " + QualityParameter.ActualName + " could not be found, or not in the same quantity as there are parents.");
if (AlphaParameter.ActualValue == null || BetaParameter.ActualValue == null) throw new InvalidOperationException("BlendAlphaBetaCrossover: Parameter " + AlphaParameter.ActualName + " or paramter " + BetaParameter.ActualName + " could not be found.");
ItemArray qualities = QualityParameter.ActualValue;
bool maximization = MaximizationParameter.ActualValue.Value;
if (maximization && qualities[0].Value >= qualities[1].Value || !maximization && qualities[0].Value <= qualities[1].Value)
return Apply(random, parents[0], parents[1], AlphaParameter.ActualValue, BetaParameter.ActualValue);
else {
return Apply(random, parents[1], parents[0], AlphaParameter.ActualValue, BetaParameter.ActualValue);
}
}
}
}