#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 } }