1  #region License Information


2  /* HeuristicLab


3  * Copyright (C) 20022018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)


4  *


5  * This file is part of HeuristicLab.


6  *


7  * HeuristicLab is free software: you can redistribute it and/or modify


8  * it under the terms of the GNU General Public License as published by


9  * the Free Software Foundation, either version 3 of the License, or


10  * (at your option) any later version.


11  *


12  * HeuristicLab is distributed in the hope that it will be useful,


13  * but WITHOUT ANY WARRANTY; without even the implied warranty of


14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the


15  * GNU General Public License for more details.


16  *


17  * You should have received a copy of the GNU General Public License


18  * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.


19  */


20  #endregion


21 


22  using System;


23  using HeuristicLab.Common;


24  using HeuristicLab.Core;


25  using HeuristicLab.Data;


26  using HeuristicLab.Parameters;


27  using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;


28 


29  namespace HeuristicLab.Encodings.RealVectorEncoding {


30  /// <summary>


31  /// Performs the simulated binary crossover (SBX) on a vector of real values such that each position is either crossed contracted or expanded with a certain probability.


32  /// The probability distribution is designed such that the children will lie closer to their parents as is the case with the single point binary crossover.


33  /// </summary>


34  /// <remarks>


35  /// It is implemented as described in Deb, K. and Agrawal, R. B. 1995. Simulated binary crossover for continuous search space. Complex Systems, 9, pp. 115148.


36  /// </remarks>


37  [Item("SimulatedBinaryCrossover", "The simulated binary crossover (SBX) is implemented as described in Deb, K. and Agrawal, R. B. 1995. Simulated binary crossover for continuous search space. Complex Systems, 9, pp. 115148.")]


38  [StorableClass]


39  public class SimulatedBinaryCrossover : RealVectorCrossover {


40  /// <summary>


41  /// The parameter must be greater or equal than 0. Common values are in the range [0;5] and more often just [2;5].


42  /// </summary>


43  public ValueLookupParameter<DoubleValue> ContiguityParameter {


44  get { return (ValueLookupParameter<DoubleValue>)Parameters["Contiguity"]; }


45  }


46 


47  [StorableConstructor]


48  protected SimulatedBinaryCrossover(bool deserializing) : base(deserializing) { }


49  protected SimulatedBinaryCrossover(SimulatedBinaryCrossover original, Cloner cloner) : base(original, cloner) { }


50  /// <summary>


51  /// Initializes a new instance of <see cref="SimulatedBinaryCrossover"/> with one


52  /// parameter (<c>Contiguity</c>).


53  /// </summary>


54  public SimulatedBinaryCrossover()


55  : base() {


56  Parameters.Add(new ValueLookupParameter<DoubleValue>("Contiguity", "Specifies whether the crossover should produce very different (small value) or very similar (large value) children. Valid values must be greater or equal to 0.", new DoubleValue(2)));


57  }


58 


59  public override IDeepCloneable Clone(Cloner cloner) {


60  return new SimulatedBinaryCrossover(this, cloner);


61  }


62 


63  /// <summary>


64  /// Performs the simulated binary crossover on a real vector. Each position is crossed with a probability of 50% and if crossed either a contracting crossover or an expanding crossover is performed, again with equal probability.


65  /// For more details refer to the paper by Deb and Agrawal.


66  /// </summary>


67  /// <exception cref="ArgumentException">Thrown when the parents' vectors are of unequal length or when <paramref name="contiguity"/> is smaller than 0.</exception>


68  /// <remarks>


69  /// The manipulated value is not restricted by the (possibly) specified lower and upper bounds. Use the <see cref="BoundsChecker"/> to correct the values after performing the crossover.


70  /// </remarks>


71  /// <param name="random">The random number generator to use.</param>


72  /// <param name="parent1">The first parent vector.</param>


73  /// <param name="parent2">The second parent vector.</param>


74  /// <param name="contiguity">The contiguity value that specifies how close a child should be to its parents (larger value means closer). The value must be greater or equal than 0. Typical values are in the range [2;5].</param>


75  /// <returns>The vector resulting from the crossover.</returns>


76  public static RealVector Apply(IRandom random, RealVector parent1, RealVector parent2, DoubleValue contiguity) {


77  if (parent1.Length != parent2.Length) throw new ArgumentException("SimulatedBinaryCrossover: Parents are of unequal length");


78  if (contiguity.Value < 0) throw new ArgumentException("SimulatedBinaryCrossover: Contiguity value is smaller than 0", "contiguity");


79  int length = parent1.Length;


80  RealVector result = new RealVector(length);


81  for (int i = 0; i < length; i++) {


82  if (length == 1  random.NextDouble() < 0.5) { // cross this variable


83  double u = random.NextDouble();


84  double beta = 0;


85  if (u < 0.5) { // if u is smaller than 0.5 perform a contracting crossover


86  beta = Math.Pow(2 * u, 1.0 / (contiguity.Value + 1));


87  } else if (u > 0.5) { // otherwise perform an expanding crossover


88  beta = Math.Pow(0.5 / (1.0  u), 1.0 / (contiguity.Value + 1));


89  } else if (u == 0.5)


90  beta = 1;


91 


92  if (random.NextDouble() < 0.5)


93  result[i] = ((parent1[i] + parent2[i]) / 2.0)  beta * 0.5 * Math.Abs(parent1[i]  parent2[i]);


94  else


95  result[i] = ((parent1[i] + parent2[i]) / 2.0) + beta * 0.5 * Math.Abs(parent1[i]  parent2[i]);


96  } else result[i] = parent1[i];


97  }


98  return result;


99  }


100 


101  /// <summary>


102  /// Checks number of parents, availability of the parameters and forwards the call to <see cref="Apply(IRandom, RealVector, RealVector, DoubleValue)"/>.


103  /// </summary>


104  /// <exception cref="ArgumentException">Thrown when there are not exactly 2 parents or when the contiguity parameter could not be found.</exception>


105  /// <param name="random">The random number generator.</param>


106  /// <param name="parents">The collection of parents (must be of size 2).</param>


107  /// <returns>The real vector resulting from the crossover.</returns>


108  protected override RealVector Cross(IRandom random, ItemArray<RealVector> parents) {


109  if (parents.Length != 2) throw new ArgumentException("SimulatedBinaryCrossover: The number of parents is not equal to 2");


110  if (ContiguityParameter.ActualValue == null) throw new InvalidOperationException("SimulatedBinaryCrossover: Parameter " + ContiguityParameter.ActualName + " could not be found.");


111  return Apply(random, parents[0], parents[1], ContiguityParameter.ActualValue);


112  }


113  }


114  }

