#region License Information
/* HeuristicLab
* Copyright (C) 2002-2014 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 System.Collections.Generic;
using System.Drawing;
using System.Linq;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Encodings.BinaryVectorEncoding;
using HeuristicLab.Encodings.IntegerVectorEncoding;
using HeuristicLab.Encodings.PermutationEncoding;
using HeuristicLab.Encodings.RealVectorEncoding;
using HeuristicLab.Optimization;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.PluginInfrastructure;
namespace HeuristicLab.Problems.Programmable {
[Item("Programmable Problem (multi-objective)", "Represents a multi-objective problem that can be programmed.")]
[Creatable("Problems")]
[StorableClass]
public class MultiObjectiveProgrammableProblem : MultiObjectiveHeuristicOptimizationProblem, IParameterizedNamedItem, IStorableContent {
public string Filename { get; set; }
public static new Image StaticItemImage {
get { return Common.Resources.VSImageLibrary.Script; }
}
public new ParameterCollection Parameters {
get { return base.Parameters; }
}
IKeyedItemCollection IParameterizedItem.Parameters {
get { return Parameters; }
}
public IValueParameter ProblemDefinitionParameter {
get { return (IValueParameter)Parameters["ProblemDefinition"]; }
}
protected IValueParameter EncodingParameter {
get { return (IValueParameter)Parameters["Encoding"]; }
}
public IMultiObjectiveProblemDefinition ProblemDefinition {
get { return ProblemDefinitionParameter.Value; }
set { ProblemDefinitionParameter.Value = value; }
}
[Storable]
protected List DynamicEncodingParameters;
[StorableConstructor]
protected MultiObjectiveProgrammableProblem(bool deserializing) : base(deserializing) { }
protected MultiObjectiveProgrammableProblem(MultiObjectiveProgrammableProblem original, Cloner cloner)
: base(original, cloner) {
DynamicEncodingParameters = original.DynamicEncodingParameters.Select(cloner.Clone).ToList();
RegisterEventHandlers();
}
public MultiObjectiveProgrammableProblem()
: base(new MultiObjectiveEvaluator(), new MultiEncodingCreator()) {
Parameters.Add(new ValueParameter("ProblemDefinition", "Defines the problem.", new MultiObjectiveProblemScript() { Name = Name }));
Parameters.Add(new ValueParameter("Encoding", "Describes which parameters exist, what they're called, what type they are and their bounds if any."));
DynamicEncodingParameters = new List();
Operators.Add(new MultiObjectiveAnalyzer());
Operators.Add(Evaluator);
Operators.Add(SolutionCreator);
RegisterEventHandlers();
}
public override IDeepCloneable Clone(Cloner cloner) {
return new MultiObjectiveProgrammableProblem(this, cloner);
}
[StorableHook(HookType.AfterDeserialization)]
// ReSharper disable UnusedMember.Local
private void AfterDeserialization() {
RegisterEventHandlers();
}
// ReSharper restore UnusedMember.Local
private void RegisterEventHandlers() {
ProblemDefinitionParameter.ValueChanged += ProblemDefinitionParameterOnValueChanged;
RegisterHostInstanceChanges();
}
private void ProblemDefinitionParameterOnValueChanged(object sender, EventArgs eventArgs) {
RegisterHostInstanceChanges();
Parameterize();
}
private void RegisterHostInstanceChanges() {
ProblemDefinitionParameter.Value.ProblemDefinitionChanged += ProblemDefinitionChanged;
ProblemDefinitionParameter.Value.NameChanged += ProblemDefinitionHostOnNameChanged;
}
private void ProblemDefinitionHostOnNameChanged(object sender, EventArgs eventArgs) {
if (sender != ProblemDefinitionParameter.Value) return;
Name = ProblemDefinitionParameter.Value.Name;
}
protected override void OnNameChanged() {
base.OnNameChanged();
ProblemDefinitionParameter.Value.Name = Name;
}
protected override void OnEvaluatorChanged() {
base.OnEvaluatorChanged();
Parameterize();
}
protected virtual void ProblemDefinitionChanged(object sender, EventArgs eventArgs) {
Parameterize();
}
protected virtual void Parameterize() {
var definition = ProblemDefinitionParameter.Value;
if (definition == null) return;
IEncoding encoding = definition.Encoding;
EncodingParameter.Value = encoding;
Maximization = new BoolArray(definition.Maximization);
Evaluator.EncodingParameter.ActualName = EncodingParameter.Name;
Evaluator.ProblemDefinitionParameter.ActualName = ProblemDefinitionParameter.Name;
foreach (var evalOp in Operators.OfType()) {
evalOp.EncodingParameter.ActualName = EncodingParameter.Name;
evalOp.ProblemDefinitionParameter.ActualName = ProblemDefinitionParameter.Name;
}
foreach (var analyzeOp in Operators.OfType()) {
analyzeOp.EncodingParameter.ActualName = EncodingParameter.Name;
analyzeOp.ProblemDefinitionParameter.ActualName = ProblemDefinitionParameter.Name;
analyzeOp.QualitiesParameter.ActualName = Evaluator.QualitiesParameter.ActualName;
}
foreach (var param in DynamicEncodingParameters)
if (Parameters.Contains(param)) Parameters.Remove(param);
DynamicEncodingParameters.Clear();
var creator = ConfigureCreator(encoding);
foreach (var param in DynamicEncodingParameters) {
param.Hidden = true;
Parameters.Add(param);
}
var multiEncoding = encoding as MultiEncoding;
if (multiEncoding != null) {
ConfigureMultiVectorEncodingOperators((MultiEncodingCreator)creator, multiEncoding);
} else {
ConfigureSingleEncodingOperators(creator, encoding);
}
}
protected virtual ISolutionCreator ConfigureCreator(IEncoding encoding) {
#region Configure RealVector Creator
var realEnc = encoding as RealEncoding;
if (realEnc != null) {
DynamicEncodingParameters.AddRange(realEnc.Parameters);
return realEnc.DefaultSolutionCreator;
}
#endregion
#region Configure BinaryVector Creator
var binEnc = encoding as BinaryEncoding;
if (binEnc != null) {
DynamicEncodingParameters.AddRange(binEnc.Parameters);
return binEnc.DefaultSolutionCreator;
}
#endregion
#region Configure IntegerVector Creator
var intEnc = encoding as IntegerEncoding;
if (intEnc != null) {
DynamicEncodingParameters.AddRange(intEnc.Parameters);
return intEnc.DefaultSolutionCreator;
}
#endregion
#region Configure MultiEncoding Creator
var multiEncoding = encoding as MultiEncoding;
if (multiEncoding != null) {
var creator = new MultiEncodingCreator();
foreach (var enc in multiEncoding.Encodings) {
if (enc is MultiEncoding) throw new InvalidOperationException("MultiEncoding within a MultiEncoding is not supported.");
creator.Operators.Add(ConfigureCreator(enc));
}
return creator;
}
#endregion
#region Configure Permutation Creator
var permEnc = encoding as PermutationEncoding;
if (permEnc != null) {
var l = new ValueParameter(permEnc.Name + "Length", permEnc.Length);
DynamicEncodingParameters.Add(l);
var creator = new RandomPermutationCreator();
creator.PermutationParameter.ActualName = permEnc.Name;
creator.LengthParameter.ActualName = l.Name;
creator.PermutationTypeParameter.Value = permEnc.Type;
return creator;
}
#endregion
throw new ArgumentException(string.Format("Encoding {0} is unknown.", encoding != null ? encoding.GetType().FullName : "(null)"));
}
protected virtual void ConfigureSingleEncodingOperators(ISolutionCreator newCreator, IEncoding encoding) {
// remove all multiencoding operators
Operators.RemoveAll(x => x is MultiEncodingCrossover
|| x is MultiEncodingManipulator
|| x is MultiEncodingCreator);
#region Configure Operators for BinaryVectorEncoding
var binCreator = newCreator as IBinaryVectorCreator;
if (binCreator != null) {
var paramName = binCreator.BinaryVectorParameter.ActualName;
// do not replace a binary vector creator that was manually set
if (!(SolutionCreator is IBinaryVectorCreator) || ((IBinaryVectorCreator)SolutionCreator).BinaryVectorParameter.ActualName != paramName) {
Operators.Remove(SolutionCreator);
SolutionCreator = newCreator;
Operators.Add(SolutionCreator);
}
#region Wire BinaryVector Crossovers
var crossovers = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var xo in crossovers) {
xo.ChildParameter.ActualName = binCreator.BinaryVectorParameter.ActualName;
xo.ChildParameter.Hidden = true;
xo.ParentsParameter.ActualName = binCreator.BinaryVectorParameter.ActualName;
xo.ParentsParameter.Hidden = true;
}
Operators.AddRange(crossovers.Except(Operators.OfType()));
#endregion
#region Wire BinaryVector Manipulators
var manipulators = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var m in manipulators) {
m.BinaryVectorParameter.ActualName = binCreator.BinaryVectorParameter.ActualName;
m.BinaryVectorParameter.Hidden = true;
}
Operators.AddRange(manipulators.Except(Operators.OfType()));
#endregion
#region Wire BinaryVector ShakingOperators
var shakingOperators = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var so in shakingOperators) {
so.BinaryVectorParameter.ActualName = paramName;
so.BinaryVectorParameter.Hidden = true;
}
Operators.AddRange(shakingOperators.Except(Operators.OfType()));
#endregion
} else {
Operators.RemoveAll(x => x is IBinaryVectorCrossover
|| x is IBinaryVectorManipulator
|| x is IBinaryVectorMultiNeighborhoodShakingOperator);
}
#endregion
#region Configure Operators for IntegerVectorEncoding
var intCreator = newCreator as IIntegerVectorCreator;
if (intCreator != null) {
var paramName = intCreator.IntegerVectorParameter.ActualName;
// do not replace an integer vector creator that was manually set
if (!(SolutionCreator is IIntegerVectorCreator)
|| ((IIntegerVectorCreator)SolutionCreator).IntegerVectorParameter.ActualName != intCreator.IntegerVectorParameter.ActualName) {
Operators.Remove(SolutionCreator);
SolutionCreator = newCreator;
Operators.Add(SolutionCreator);
}
#region Wire IntegerVector Crossovers
var crossovers = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var xo in crossovers) {
xo.ChildParameter.ActualName = intCreator.IntegerVectorParameter.ActualName;
xo.ChildParameter.Hidden = true;
xo.ParentsParameter.ActualName = intCreator.IntegerVectorParameter.ActualName;
xo.ParentsParameter.Hidden = true;
var bx = xo as IBoundedIntegerVectorOperator;
if (bx != null) {
bx.BoundsParameter.ActualName = intCreator.BoundsParameter.ActualName;
bx.BoundsParameter.Hidden = true;
}
}
Operators.AddRange(crossovers.Except(Operators.OfType()));
#endregion
#region Wire IntegerVector Manipulators
var manipulators = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var m in manipulators) {
m.IntegerVectorParameter.ActualName = intCreator.IntegerVectorParameter.ActualName;
m.IntegerVectorParameter.Hidden = true;
var sm = m as ISelfAdaptiveManipulator;
if (sm != null) {
var p = sm.StrategyParameterParameter as ILookupParameter;
if (p != null) {
p.ActualName = paramName + "Strategy";
p.Hidden = true;
}
}
var bm = m as IBoundedIntegerVectorOperator;
if (bm != null) {
bm.BoundsParameter.ActualName = intCreator.BoundsParameter.ActualName;
bm.BoundsParameter.Hidden = true;
}
}
Operators.AddRange(manipulators.Except(Operators.OfType()));
#region Wire IntegerVector StrategyParameters for SelfAdaptiveManipulators
var strategyOperators = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
var problemSize = ((IntegerEncoding)encoding).Length;
var b = ((IntegerEncoding)encoding).Bounds;
var bounds = new DoubleMatrix(b.Rows, b.Columns);
for (var i = 0; i < bounds.Rows; i++) {
bounds[i, 1] = (int)Math.Ceiling(0.33 * (b[i, 1] - b[i, 0]));
bounds[i, 0] = 0;
if (bounds.Columns > 2) bounds[i, 2] = b[i, 2];
}
foreach (var s in strategyOperators) {
var c = s as IIntegerVectorStdDevStrategyParameterCreator;
if (c != null) {
c.BoundsParameter.Value = (DoubleMatrix)bounds.Clone();
c.LengthParameter.ActualName = intCreator.LengthParameter.ActualName;
c.StrategyParameterParameter.ActualName = paramName + "Strategy";
}
var m = s as IIntegerVectorStdDevStrategyParameterManipulator;
if (m != null) {
m.BoundsParameter.Value = (DoubleMatrix)bounds.Clone();
m.StrategyParameterParameter.ActualName = paramName + "Strategy";
}
var mm = s as Encodings.IntegerVectorEncoding.StdDevStrategyVectorManipulator;
if (mm != null) {
mm.GeneralLearningRateParameter.Value = new DoubleValue(1.0 / Math.Sqrt(2 * problemSize));
mm.LearningRateParameter.Value = new DoubleValue(1.0 / Math.Sqrt(2 * Math.Sqrt(problemSize)));
}
var x = s as IIntegerVectorStdDevStrategyParameterCrossover;
if (x != null) {
x.ParentsParameter.ActualName = paramName + "Strategy";
x.StrategyParameterParameter.ActualName = paramName + "Strategy";
}
}
Operators.AddRange(strategyOperators.Except(Operators.OfType()));
#endregion
#endregion
#region Wire IntegerVector ShakingOperators
var shakingOperators = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var so in shakingOperators) {
so.IntegerVectorParameter.ActualName = paramName;
so.IntegerVectorParameter.Hidden = true;
}
Operators.AddRange(shakingOperators.Except(Operators.OfType()));
#endregion
} else {
Operators.RemoveAll(x => x is IIntegerVectorCrossover
|| x is IIntegerVectorManipulator
|| x is IIntegerVectorStdDevStrategyParameterOperator
|| x is IIntegerVectorMultiNeighborhoodShakingOperator);
}
#endregion
#region Configure Operators for RealVectorEncoding
var realCreator = newCreator as IRealVectorCreator;
if (realCreator != null) {
var paramName = realCreator.RealVectorParameter.ActualName;
// do not replace a real vector creator that was manually set
if (!(SolutionCreator is IRealVectorCreator)
|| ((IRealVectorCreator)SolutionCreator).RealVectorParameter.ActualName != realCreator.RealVectorParameter.ActualName) {
Operators.Remove(SolutionCreator);
SolutionCreator = newCreator;
Operators.Add(SolutionCreator);
}
#region Wire RealVector Crossovers
var crossovers = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var xo in crossovers) {
xo.ChildParameter.ActualName = paramName;
xo.ChildParameter.Hidden = true;
xo.ParentsParameter.ActualName = paramName;
xo.ParentsParameter.Hidden = true;
xo.BoundsParameter.ActualName = realCreator.BoundsParameter.ActualName;
xo.BoundsParameter.Hidden = true;
}
Operators.AddRange(crossovers.Except(Operators.OfType()));
#endregion
#region Wire RealVector Manipulators
var manipulators = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var m in manipulators) {
m.RealVectorParameter.ActualName = paramName;
m.RealVectorParameter.Hidden = true;
m.BoundsParameter.ActualName = realCreator.BoundsParameter.ActualName;
m.BoundsParameter.Hidden = true;
var sm = m as ISelfAdaptiveManipulator;
if (sm != null) {
var p = sm.StrategyParameterParameter as ILookupParameter;
if (p != null) {
p.ActualName = paramName + "Strategy";
p.Hidden = true;
}
}
}
Operators.AddRange(manipulators.Except(Operators.OfType()));
#region Wire RealVector Strategy Parameters for SelfAdaptiveManipulators
var strategyOperators = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
var problemSize = ((RealEncoding)encoding).Length;
var bounds = (DoubleMatrix)((RealEncoding)encoding).Bounds.Clone();
for (var i = 0; i < bounds.Rows; i++) {
bounds[i, 1] = 0.1 * (bounds[i, 1] - bounds[i, 0]);
bounds[i, 0] = 0;
}
foreach (var s in strategyOperators) {
var c = s as IRealVectorStdDevStrategyParameterCreator;
if (c != null) {
c.BoundsParameter.Value = (DoubleMatrix)bounds.Clone();
c.LengthParameter.ActualName = realCreator.LengthParameter.ActualName;
c.StrategyParameterParameter.ActualName = paramName + "Strategy";
}
var m = s as IRealVectorStdDevStrategyParameterManipulator;
if (m != null) {
m.BoundsParameter.Value = (DoubleMatrix)bounds.Clone();
m.StrategyParameterParameter.ActualName = paramName + "Strategy";
}
var mm = s as Encodings.RealVectorEncoding.StdDevStrategyVectorManipulator;
if (mm != null) {
mm.GeneralLearningRateParameter.Value = new DoubleValue(1.0 / Math.Sqrt(2 * problemSize));
mm.LearningRateParameter.Value = new DoubleValue(1.0 / Math.Sqrt(2 * Math.Sqrt(problemSize)));
}
var x = s as IRealVectorStdDevStrategyParameterCrossover;
if (x != null) {
x.ParentsParameter.ActualName = paramName + "Strategy";
x.StrategyParameterParameter.ActualName = paramName + "Strategy";
}
}
Operators.AddRange(strategyOperators.Except(Operators.OfType()));
#endregion
#endregion
#region Wire RealVector ParticleCreators
var particleCreators = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var pc in particleCreators) {
pc.RealVectorParameter.ActualName = paramName;
pc.RealVectorParameter.Hidden = true;
pc.BoundsParameter.ActualName = realCreator.BoundsParameter.ActualName;
pc.BoundsParameter.Hidden = true;
pc.ProblemSizeParameter.ActualName = realCreator.LengthParameter.ActualName;
pc.ProblemSizeParameter.Hidden = true;
}
Operators.AddRange(particleCreators.Except(Operators.OfType()));
#endregion
#region Wire RealVector ParticleUpdaters
var particleUpdaters = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var pu in particleUpdaters) {
pu.RealVectorParameter.ActualName = paramName;
pu.RealVectorParameter.Hidden = true;
pu.BoundsParameter.ActualName = realCreator.BoundsParameter.ActualName;
pu.BoundsParameter.Hidden = true;
}
Operators.AddRange(particleUpdaters.Except(Operators.OfType()));
#endregion
#region Wire RealVector SwarmUpdaters
var swarmUpdaters = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var su in swarmUpdaters) {
su.RealVectorParameter.ActualName = paramName;
su.RealVectorParameter.Hidden = true;
su.MaximizationParameter.ActualName = MaximizationParameter.Name;
su.MaximizationParameter.Hidden = true;
}
Operators.AddRange(swarmUpdaters.Except(Operators.OfType()));
#endregion
#region Wire RealVector ShakingOperators
var shakingOperators = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var so in shakingOperators) {
so.RealVectorParameter.ActualName = paramName;
so.RealVectorParameter.Hidden = true;
}
Operators.AddRange(shakingOperators.Except(Operators.OfType()));
#endregion
} else {
Operators.RemoveAll(x => x is IRealVectorCrossover
|| x is IRealVectorManipulator
|| x is IRealVectorStdDevStrategyParameterOperator
|| x is IRealVectorParticleCreator
|| x is IRealVectorParticleUpdater
|| x is IRealVectorSwarmUpdater
|| x is IRealVectorMultiNeighborhoodShakingOperator);
}
#endregion
#region Configure Operators for PermutationEncoding
var permCreator = newCreator as IPermutationCreator;
if (permCreator != null) {
var paramName = permCreator.PermutationParameter.ActualName;
// do not replace a permutation creator that was manually set
if (!(SolutionCreator is IPermutationCreator)
|| ((IPermutationCreator)SolutionCreator).PermutationParameter.ActualName != permCreator.PermutationParameter.ActualName) {
Operators.Remove(SolutionCreator);
SolutionCreator = newCreator;
Operators.Add(SolutionCreator);
}
#region Wire Permutation Crossovers
var crossovers = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var xo in crossovers) {
xo.ChildParameter.ActualName = permCreator.PermutationParameter.ActualName;
xo.ChildParameter.Hidden = true;
xo.ParentsParameter.ActualName = permCreator.PermutationParameter.ActualName;
xo.ParentsParameter.Hidden = true;
}
Operators.AddRange(crossovers.Except(Operators.OfType()));
#endregion
#region Wire Permutation Manipulators
var manipulators = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var m in manipulators) {
m.PermutationParameter.ActualName = permCreator.PermutationParameter.ActualName;
m.PermutationParameter.Hidden = true;
}
Operators.AddRange(manipulators.Except(Operators.OfType()));
#endregion
#region Wire Permutation ShakingOperators
var shakingOperators = Operators.OfType()
.Union(ApplicationManager.Manager.GetInstances(), new TypeEqualityComparer())
.ToList();
foreach (var op in shakingOperators) {
op.PermutationParameter.ActualName = paramName;
op.PermutationParameter.Hidden = true;
}
Operators.AddRange(shakingOperators.Except(Operators.OfType()));
#endregion
} else {
Operators.RemoveAll(x => x is IPermutationCrossover
|| x is IPermutationManipulator
|| x is IPermutationMultiNeighborhoodShakingOperator);
}
#endregion
}
protected virtual void ConfigureMultiVectorEncodingOperators(MultiEncodingCreator newCreator, MultiEncoding encoding) {
var newBinParams = new HashSet(newCreator.Operators.OfType().Select(x => x.BinaryVectorParameter.ActualName));
var newIntParams = new HashSet(newCreator.Operators.OfType().Select(x => x.IntegerVectorParameter.ActualName));
var newRealParams = new HashSet(newCreator.Operators.OfType().Select(x => x.RealVectorParameter.ActualName));
var newPermParams = new HashSet(newCreator.Operators.OfType().Select(x => x.PermutationParameter.ActualName));
var oldCreator = SolutionCreator as MultiEncodingCreator;
if (oldCreator == null) SolutionCreator = newCreator;
else {
#region Configure BinaryVector Creator
var oldBinParams = new HashSet(oldCreator.Operators.OfType().Select(x => x.BinaryVectorParameter.ActualName));
foreach (var toAdd in newBinParams.Except(oldBinParams)) {
oldCreator.Operators.Add(newCreator.Operators.OfType().Single(x => x.BinaryVectorParameter.ActualName == toAdd));
}
foreach (var toRemove in oldBinParams.Except(newBinParams)) {
var op = oldCreator.Operators.OfType().SingleOrDefault(x => x.BinaryVectorParameter.ActualName == toRemove);
if (op != null) oldCreator.Operators.Remove(op);
}
#endregion
#region Configure IntegerVector Creator
var oldIntParams = new HashSet(oldCreator.Operators.OfType().Select(x => x.IntegerVectorParameter.ActualName));
foreach (var toAdd in newIntParams.Except(oldIntParams)) {
oldCreator.Operators.Add(newCreator.Operators.OfType().Single(x => x.IntegerVectorParameter.ActualName == toAdd));
}
foreach (var toRemove in oldIntParams.Except(newIntParams)) {
var op = oldCreator.Operators.OfType().SingleOrDefault(x => x.IntegerVectorParameter.ActualName == toRemove);
if (op != null) oldCreator.Operators.Remove(op);
}
#endregion
#region Configure RealVector Creator
var oldRealParams = new HashSet(oldCreator.Operators.OfType().Select(x => x.RealVectorParameter.ActualName));
foreach (var toAdd in newRealParams.Except(oldRealParams)) {
oldCreator.Operators.Add(newCreator.Operators.OfType().Single(x => x.RealVectorParameter.ActualName == toAdd));
}
foreach (var toRemove in oldRealParams.Except(newRealParams)) {
var op = oldCreator.Operators.OfType().SingleOrDefault(x => x.RealVectorParameter.ActualName == toRemove);
if (op != null) oldCreator.Operators.Remove(op);
}
#endregion
#region Configure Permutation Creator
var oldPermParams = new HashSet(oldCreator.Operators.OfType().Select(x => x.PermutationParameter.ActualName));
foreach (var toAdd in newPermParams.Except(oldPermParams)) {
oldCreator.Operators.Add(newCreator.Operators.OfType().Single(x => x.PermutationParameter.ActualName == toAdd));
}
foreach (var toRemove in oldPermParams.Except(newPermParams)) {
var op = oldCreator.Operators.OfType().SingleOrDefault(x => x.PermutationParameter.ActualName == toRemove);
if (op != null) oldCreator.Operators.Remove(op);
}
// we also have to sync the permutation type (in case this changes, as it is a value parameter)
foreach (var intersect in newPermParams.Intersect(oldPermParams)) {
var oldPermCreator = oldCreator.Operators.OfType().Single(x => x.PermutationParameter.ActualName == intersect);
var newPermCreator = newCreator.Operators.OfType().Single(x => x.PermutationParameter.ActualName == intersect);
oldPermCreator.PermutationTypeParameter.Value = newPermCreator.PermutationTypeParameter.Value;
}
#endregion
}
// crossover and manipulator for multi-vector encoding
// the condition checks if a multi-vector encoding is to be updated (there already exists ParameterVectorCrossover and ParameterVectorManipulator)
if (Operators.OfType().Any() && Operators.OfType().Any()) {
#region Update existing multi-vector encoding
#region Update ParameterVector Crossover ...
foreach (var oldXo in Operators.OfType()) {
#region ... for binary parameters
var oldBinParams = new HashSet(oldXo.Operators.OfType().Select(x => x.ChildParameter.ActualName));
foreach (var toAdd in newBinParams.Except(oldBinParams))
oldXo.Operators.Add(GetDefaultBinaryCrossover(toAdd, encoding));
foreach (var toRemove in oldBinParams.Except(newBinParams)) {
var op = oldXo.Operators.OfType().SingleOrDefault(x => x.ChildParameter.ActualName == toRemove);
if (op != null) oldXo.Operators.Remove(op);
}
#endregion
#region ... for integer parameters
var oldIntParams = new HashSet(oldXo.Operators.OfType().Select(x => x.ChildParameter.ActualName));
foreach (var toAdd in newIntParams.Except(oldIntParams))
oldXo.Operators.Add(GetDefaultIntegerCrossover(toAdd, encoding));
foreach (var toRemove in oldIntParams.Except(newIntParams)) {
var op = oldXo.Operators.OfType().SingleOrDefault(x => x.ChildParameter.ActualName == toRemove);
if (op != null) oldXo.Operators.Remove(op);
}
#endregion
#region ... for real parameters
var oldRealParams = new HashSet(oldXo.Operators.OfType().Select(x => x.ChildParameter.ActualName));
foreach (var toAdd in newRealParams.Except(oldRealParams))
oldXo.Operators.Add(GetDefaultRealCrossover(toAdd, encoding));
foreach (var toRemove in oldRealParams.Except(newRealParams)) {
var op = oldXo.Operators.OfType().SingleOrDefault(x => x.ChildParameter.ActualName == toRemove);
if (op != null) oldXo.Operators.Remove(op);
}
#endregion
#region ... for permutation parameters
var oldPermParams = new HashSet(oldXo.Operators.OfType().Select(x => x.ChildParameter.ActualName));
foreach (var toAdd in newPermParams.Except(oldPermParams))
oldXo.Operators.Add(GetDefaultPermutationCrossover(toAdd, encoding));
foreach (var toRemove in oldPermParams.Except(newPermParams)) {
var op = oldXo.Operators.OfType().SingleOrDefault(x => x.ChildParameter.ActualName == toRemove);
if (op != null) oldXo.Operators.Remove(op);
}
#endregion
}
#endregion
#region Update ParameterVector Manipulator ...
foreach (var oldM in Operators.OfType()) {
#region ... for binary parameters
var oldBinParams = new HashSet(oldM.Operators.OfType().Select(x => x.BinaryVectorParameter.ActualName));
foreach (var toAdd in newBinParams.Except(oldBinParams))
oldM.Operators.Add(GetDefaultBinaryManipulator(toAdd, encoding));
foreach (var toRemove in oldBinParams.Except(newBinParams)) {
var op = oldM.Operators.OfType().SingleOrDefault(x => x.BinaryVectorParameter.ActualName == toRemove);
if (op != null) oldM.Operators.Remove(op);
}
#endregion
#region ... for integer parameters
var oldIntParams = new HashSet(oldM.Operators.OfType().Select(x => x.IntegerVectorParameter.ActualName));
foreach (var toAdd in newIntParams.Except(oldIntParams))
oldM.Operators.Add(GetDefaultIntegerManipulator(toAdd, encoding));
foreach (var toRemove in oldIntParams.Except(newIntParams)) {
var op = oldM.Operators.OfType().SingleOrDefault(x => x.IntegerVectorParameter.ActualName == toRemove);
if (op != null) oldM.Operators.Remove(op);
}
#endregion
#region ... for real parameters
var oldRealParams = new HashSet(oldM.Operators.OfType().Select(x => x.RealVectorParameter.ActualName));
foreach (var toAdd in newRealParams.Except(oldRealParams))
oldM.Operators.Add(GetDefaultRealManipulator(toAdd, encoding));
foreach (var toRemove in oldRealParams.Except(newRealParams)) {
var op = oldM.Operators.OfType().SingleOrDefault(x => x.RealVectorParameter.ActualName == toRemove);
if (op != null) oldM.Operators.Remove(op);
}
#endregion
#region ... for permutation parameters
var oldPermParams = new HashSet(oldM.Operators.OfType().Select(x => x.PermutationParameter.ActualName));
foreach (var toAdd in newPermParams.Except(oldPermParams))
oldM.Operators.Add(GetDefaultPermutationManipulator(toAdd, encoding));
foreach (var toRemove in oldPermParams.Except(newPermParams)) {
var op = oldM.Operators.OfType().SingleOrDefault(x => x.PermutationParameter.ActualName == toRemove);
if (op != null) oldM.Operators.Remove(op);
}
#endregion
}
#endregion
#endregion
} else {
#region Handle transition from single-vector to multi-vector encoding
Operators.RemoveAll(x => x is ICrossover);
Operators.RemoveAll(x => x is IManipulator);
Operators.RemoveAll(x => x is IStrategyParameterCreator || x is IStrategyParameterManipulator || x is IStrategyParameterCrossover);
Operators.RemoveAll(x => x is IParticleCreator);
Operators.RemoveAll(x => x is IParticleUpdater);
Operators.RemoveAll(x => x is ISwarmUpdater);
Operators.RemoveAll(x => x is IMultiNeighborhoodShakingOperator);
var crossover = new MultiEncodingCrossover();
var manipulator = new MultiEncodingManipulator();
foreach (var enc in encoding.Encodings) {
if (enc is BinaryEncoding) {
crossover.Operators.Add(GetDefaultBinaryCrossover(enc.Name, encoding));
manipulator.Operators.Add(GetDefaultBinaryManipulator(enc.Name, encoding));
continue;
}
var intConfig = enc as IntegerEncoding;
if (intConfig != null) {
crossover.Operators.Add(GetDefaultIntegerCrossover(enc.Name, encoding));
manipulator.Operators.Add(GetDefaultIntegerManipulator(enc.Name, encoding));
continue;
}
var realConfig = enc as RealEncoding;
if (realConfig != null) {
crossover.Operators.Add(GetDefaultRealCrossover(enc.Name, encoding));
manipulator.Operators.Add(GetDefaultRealManipulator(enc.Name, encoding));
continue;
}
var permConfig = enc as PermutationEncoding;
if (permConfig != null) {
crossover.Operators.Add(GetDefaultPermutationCrossover(enc.Name, encoding));
manipulator.Operators.Add(GetDefaultPermutationManipulator(enc.Name, encoding));
continue;
}
throw new InvalidOperationException("Unknown type for parameter " + enc.Name);
}
Operators.Add(crossover);
Operators.Add(manipulator);
#endregion
}
}
#region GetDefaultOperators for Crossovers and Manipulators
// ReSharper disable RedundantNameQualifier
protected virtual IBinaryVectorCrossover GetDefaultBinaryCrossover(string paramName, MultiEncoding config) {
var binConfig = (BinaryEncoding)config.Encodings[paramName];
IBinaryVectorCrossover binXo;
if (binConfig.Length > 3) binXo = new Encodings.BinaryVectorEncoding.SinglePointCrossover();
else binXo = new Encodings.BinaryVectorEncoding.UniformCrossover();
binXo.ChildParameter.ActualName = paramName;
binXo.ParentsParameter.ActualName = paramName;
return binXo;
}
protected virtual IBinaryVectorManipulator GetDefaultBinaryManipulator(string paramName, MultiEncoding config) {
var binM = new Encodings.BinaryVectorEncoding.SomePositionsBitflipManipulator();
binM.BinaryVectorParameter.ActualName = paramName;
binM.MutationProbabilityParameter.Value = new DoubleValue(0.1);
return binM;
}
protected virtual IIntegerVectorCrossover GetDefaultIntegerCrossover(string paramName, MultiEncoding config) {
var intXo = new Encodings.IntegerVectorEncoding.RoundedBlendAlphaCrossover();
intXo.ChildParameter.ActualName = paramName;
intXo.ParentsParameter.ActualName = paramName;
intXo.BoundsParameter.ActualName = paramName + "Bounds";
return intXo;
}
protected virtual IIntegerVectorManipulator GetDefaultIntegerManipulator(string paramName, MultiEncoding configuration) {
var intM = new Encodings.IntegerVectorEncoding.UniformSomePositionsManipulator();
intM.IntegerVectorParameter.ActualName = paramName;
intM.BoundsParameter.ActualName = paramName + "Bounds";
intM.ProbabilityParameter.Value = new DoubleValue(0.1);
return intM;
}
protected virtual IRealVectorCrossover GetDefaultRealCrossover(string paramName, MultiEncoding configuration) {
var realXo = new Encodings.RealVectorEncoding.BlendAlphaCrossover();
realXo.ChildParameter.ActualName = paramName;
realXo.ParentsParameter.ActualName = paramName;
realXo.BoundsParameter.ActualName = paramName + "Bounds";
return realXo;
}
protected virtual IRealVectorManipulator GetDefaultRealManipulator(string paramName, MultiEncoding configuration) {
var realM = new Encodings.RealVectorEncoding.BreederGeneticAlgorithmManipulator();
realM.RealVectorParameter.ActualName = paramName;
realM.BoundsParameter.ActualName = paramName + "Bounds";
return realM;
}
protected virtual IPermutationCrossover GetDefaultPermutationCrossover(string paramName, MultiEncoding configuration) {
var permXo = new Encodings.PermutationEncoding.PartiallyMatchedCrossover();
permXo.ChildParameter.ActualName = paramName;
permXo.ParentsParameter.ActualName = paramName;
return permXo;
}
protected virtual IPermutationManipulator GetDefaultPermutationManipulator(string paramName, MultiEncoding configuration) {
var permM = new Encodings.PermutationEncoding.Swap2Manipulator();
permM.PermutationParameter.ActualName = paramName;
return permM;
}
// ReSharper restore RedundantNameQualifier
#endregion
}
}