#region License Information /* HeuristicLab * Copyright (C) 2002-2011 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.Linq; using HeuristicLab.Analysis; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Operators; using HeuristicLab.Optimization; using HeuristicLab.Optimization.Operators; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.PluginInfrastructure; using HeuristicLab.Random; namespace HeuristicLab.Algorithms.ParticleSwarmOptimization { [Item("Particle Swarm Optimization", "A particle swarm optimization algorithm based on the description in Pedersen, M.E.H. (2010). PhD thesis. University of Southampton.")] [Creatable("Algorithms")] [StorableClass] public sealed class ParticleSwarmOptimization : HeuristicOptimizationEngineAlgorithm, IStorableContent { #region Problem Properties public override Type ProblemType { get { return typeof(ISingleObjectiveHeuristicOptimizationProblem); } } public new ISingleObjectiveHeuristicOptimizationProblem Problem { get { return (ISingleObjectiveHeuristicOptimizationProblem)base.Problem; } set { base.Problem = value; } } public MultiAnalyzer Analyzer { get { return AnalyzerParameter.Value; } set { AnalyzerParameter.Value = value; } } public IDiscreteDoubleValueModifier OmegaUpdater { get { return OmegaUpdaterParameter.Value; } set { OmegaUpdaterParameter.Value = value; } } public IDiscreteDoubleMatrixModifier VelocityBoundsUpdater { get { return VelocityBoundsUpdaterParameter.Value; } set { VelocityBoundsUpdaterParameter.Value = value; } } #endregion #region Parameter Properties public IValueParameter SeedParameter { get { return (IValueParameter)Parameters["Seed"]; } } public IValueParameter SetSeedRandomlyParameter { get { return (IValueParameter)Parameters["SetSeedRandomly"]; } } public IValueParameter SwarmSizeParameter { get { return (IValueParameter)Parameters["SwarmSize"]; } } public IValueParameter MaxIterationsParameter { get { return (IValueParameter)Parameters["MaxIterations"]; } } public IValueParameter OmegaParameter { get { return (IValueParameter)Parameters["Omega"]; } } public IValueParameter Phi_PParameter { get { return (IValueParameter)Parameters["Phi_P"]; } } public IValueParameter Phi_GParameter { get { return (IValueParameter)Parameters["Phi_G"]; } } public IValueParameter AnalyzerParameter { get { return (IValueParameter)Parameters["Analyzer"]; } } public IValueLookupParameter VelocityBoundsParameter { get { return (IValueLookupParameter)Parameters["VelocityBounds"]; } } public ConstrainedValueParameter ParticleUpdaterParameter { get { return (ConstrainedValueParameter)Parameters["ParticleUpdater"]; } } public OptionalConstrainedValueParameter TopologyInitializerParameter { get { return (OptionalConstrainedValueParameter)Parameters["TopologyInitializer"]; } } public OptionalConstrainedValueParameter TopologyUpdaterParameter { get { return (OptionalConstrainedValueParameter)Parameters["TopologyUpdater"]; } } public OptionalConstrainedValueParameter VelocityBoundsUpdaterParameter { get { return (OptionalConstrainedValueParameter)Parameters["VelocityBoundsUpdater"]; } } public OptionalConstrainedValueParameter OmegaUpdaterParameter { get { return (OptionalConstrainedValueParameter)Parameters["OmegaUpdater"]; } } #endregion #region Properties public string Filename { get; set; } [Storable] private BestAverageWorstQualityAnalyzer qualityAnalyzer; public ITopologyInitializer TopologyInitializer { get { return TopologyInitializerParameter.Value; } set { TopologyInitializerParameter.Value = value; } } public ITopologyUpdater TopologyUpdater { get { return TopologyUpdaterParameter.Value; } set { TopologyUpdaterParameter.Value = value; } } public IParticleUpdater ParticleUpdater { get { return ParticleUpdaterParameter.Value; } set { ParticleUpdaterParameter.Value = value; } } #endregion [StorableConstructor] private ParticleSwarmOptimization(bool deserializing) : base(deserializing) { } private ParticleSwarmOptimization(ParticleSwarmOptimization original, Cloner cloner) : base(original, cloner) { qualityAnalyzer = cloner.Clone(original.qualityAnalyzer); Initialize(); } public ParticleSwarmOptimization() : base() { Parameters.Add(new ValueParameter("Seed", "The random seed used to initialize the new pseudo random number generator.", new IntValue(0))); Parameters.Add(new ValueParameter("SetSeedRandomly", "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true))); Parameters.Add(new ValueParameter("SwarmSize", "Size of the particle swarm.", new IntValue(10))); Parameters.Add(new ValueParameter("MaxIterations", "Maximal number of iterations.", new IntValue(1000))); Parameters.Add(new ValueParameter("Analyzer", "The operator used to analyze each generation.", new MultiAnalyzer())); Parameters.Add(new ValueParameter("Omega", "Weight for particle's velocity vector.", new DoubleValue(-0.2))); Parameters.Add(new ValueParameter("Phi_P", "Weight for particle's personal best position.", new DoubleValue(-0.01))); Parameters.Add(new ValueParameter("Phi_G", "Weight for global best position.", new DoubleValue(3.7))); Parameters.Add(new ValueLookupParameter("VelocityBounds", "Maximum Velocity in every dimension", new DoubleMatrix(new double[,] { { -1, 1 } }))); Parameters.Add(new ConstrainedValueParameter("ParticleUpdater", "Operator that calculates new position and velocity of a particle")); Parameters.Add(new OptionalConstrainedValueParameter("TopologyInitializer", "Creates neighborhood description vectors")); Parameters.Add(new OptionalConstrainedValueParameter("TopologyUpdater", "Updates the neighborhood description vectors")); Parameters.Add(new OptionalConstrainedValueParameter("OmegaUpdater", "Updates the omega parameter")); Parameters.Add(new OptionalConstrainedValueParameter("VelocityBoundsUpdater", "Adjusts the velocity bounds.")); ParticleUpdaterParameter.ActualValue = ParticleUpdaterParameter.ValidValues.SingleOrDefault(v => v.GetType() == typeof(TotallyConnectedParticleUpdater)); RandomCreator randomCreator = new RandomCreator(); VariableCreator variableCreator = new VariableCreator(); SolutionsCreator solutionsCreator = new SolutionsCreator(); CombinedOperator particleCreator = new CombinedOperator(); Placeholder evaluatorPlaceholder = new Placeholder(); Assigner bestPersonalQualityAssigner = new Assigner(); BestPointInitializer bestPositionInitializer = new BestPointInitializer(); Placeholder topologyInitializerPlaceholder = new Placeholder(); NeighborUpdater neighborUpdater = new NeighborUpdater(); Placeholder analyzerPlaceholder = new Placeholder(); UniformSubScopesProcessor uniformSubScopeProcessor = new UniformSubScopesProcessor(); Placeholder particleUpdaterPlaceholder = new Placeholder(); Placeholder topologyUpdaterPlaceholder = new Placeholder(); UniformSubScopesProcessor uniformSubscopesProcessor2 = new UniformSubScopesProcessor(); UniformSubScopesProcessor evaluationProcessor = new UniformSubScopesProcessor(); NeighborUpdater neighborUpdater2 = new NeighborUpdater(); Placeholder evaluatorPlaceholder2 = new Placeholder(); SwarmUpdater swarmUpdater = new SwarmUpdater(); Placeholder analyzerPlaceholder2 = new Placeholder(); IntCounter currentIterationCounter = new IntCounter(); Comparator currentIterationComparator = new Comparator(); ConditionalBranch conditionalBranch = new ConditionalBranch(); Placeholder velocityBoundsUpdaterPlaceholder = new Placeholder(); Placeholder omegaUpdaterPlaceholder = new Placeholder(); OperatorGraph.InitialOperator = randomCreator; randomCreator.SetSeedRandomlyParameter.Value = null; randomCreator.SeedParameter.Value = null; randomCreator.Successor = variableCreator; variableCreator.CollectedValues.Add(new ValueParameter("CurrentIteration", new IntValue(0))); variableCreator.Successor = solutionsCreator; solutionsCreator.NumberOfSolutionsParameter.ActualName = "SwarmSize"; solutionsCreator.EvaluatorParameter.Value = evaluatorPlaceholder; solutionsCreator.SolutionCreatorParameter.Value = particleCreator; solutionsCreator.Successor = bestPositionInitializer; InitializeParticleCreator(particleCreator); evaluatorPlaceholder.Name = "(Evaluator)"; evaluatorPlaceholder.OperatorParameter.ActualName = "Evaluator"; evaluatorPlaceholder.Successor = bestPersonalQualityAssigner; bestPersonalQualityAssigner.LeftSideParameter.ActualName = "PersonalBestQuality"; bestPersonalQualityAssigner.RightSideParameter.ActualName = "Quality"; bestPositionInitializer.Successor = topologyInitializerPlaceholder; topologyInitializerPlaceholder.Name = "(TopologyInitializer)"; topologyInitializerPlaceholder.OperatorParameter.ActualName = "TopologyInitializer"; topologyInitializerPlaceholder.Successor = neighborUpdater; neighborUpdater.Successor = analyzerPlaceholder; analyzerPlaceholder.Name = "(Analyzer)"; analyzerPlaceholder.OperatorParameter.ActualName = "Analyzer"; analyzerPlaceholder.Successor = uniformSubScopeProcessor; uniformSubScopeProcessor.Operator = particleUpdaterPlaceholder; uniformSubScopeProcessor.Successor = evaluationProcessor; particleUpdaterPlaceholder.Name = "(ParticleUpdater)"; particleUpdaterPlaceholder.OperatorParameter.ActualName = "ParticleUpdater"; evaluationProcessor.Parallel = new BoolValue(true); evaluationProcessor.Operator = evaluatorPlaceholder2; evaluationProcessor.Successor = topologyUpdaterPlaceholder; evaluatorPlaceholder2.Name = "(Evaluator)"; evaluatorPlaceholder2.OperatorParameter.ActualName = "Evaluator"; topologyUpdaterPlaceholder.Name = "(TopologyUpdater)"; topologyUpdaterPlaceholder.OperatorParameter.ActualName = "TopologyUpdater"; topologyUpdaterPlaceholder.Successor = neighborUpdater2; neighborUpdater2.Successor = uniformSubscopesProcessor2; uniformSubscopesProcessor2.Operator = swarmUpdater; uniformSubscopesProcessor2.Successor = analyzerPlaceholder2; analyzerPlaceholder2.Name = "(Analyzer)"; analyzerPlaceholder2.OperatorParameter.ActualName = "Analyzer"; analyzerPlaceholder2.Successor = currentIterationCounter; currentIterationCounter.Name = "CurrentIteration++"; currentIterationCounter.ValueParameter.ActualName = "CurrentIteration"; currentIterationCounter.Successor = omegaUpdaterPlaceholder; omegaUpdaterPlaceholder.Name = "(Omega Updater)"; omegaUpdaterPlaceholder.OperatorParameter.ActualName = "OmegaUpdater"; omegaUpdaterPlaceholder.Successor = velocityBoundsUpdaterPlaceholder; velocityBoundsUpdaterPlaceholder.Name = "(Velocity Bounds Updater)"; velocityBoundsUpdaterPlaceholder.OperatorParameter.ActualName = "VelocityBoundsUpdater"; velocityBoundsUpdaterPlaceholder.Successor = currentIterationComparator; currentIterationComparator.LeftSideParameter.ActualName = "CurrentIteration"; currentIterationComparator.Comparison = new Comparison(ComparisonType.Less); currentIterationComparator.RightSideParameter.ActualName = "MaxIterations"; currentIterationComparator.ResultParameter.ActualName = "ContinueIteration"; currentIterationComparator.Successor = conditionalBranch; conditionalBranch.Name = "ContinueIteration?"; conditionalBranch.ConditionParameter.ActualName = "ContinueIteration"; conditionalBranch.TrueBranch = uniformSubScopeProcessor; InitializeAnalyzers(); InitVelocityBoundsUpdater(); UpdateAnalyzers(); UpdateOmegaUpdater(); InitOmegaUpdater(); UpdateTopologyInitializer(); Initialize(); } public override IDeepCloneable Clone(Cloner cloner) { return new ParticleSwarmOptimization(this, cloner); } [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { Initialize(); } public override void Prepare() { if (Problem != null) { base.Prepare(); if (OmegaUpdater != null && OmegaUpdater.StartValueParameter.Value != null) { this.OmegaParameter.ActualValue = new DoubleValue(OmegaUpdaterParameter.Value.StartValueParameter.Value.Value); } if (VelocityBoundsUpdater != null && VelocityBoundsUpdater.StartValueParameter.Value != null && VelocityBoundsParameter.Value != null) { DoubleMatrix matrix = VelocityBoundsParameter.Value; for (int i = 0; i < matrix.Rows; i++) { matrix[i, 0] = -VelocityBoundsUpdater.StartValueParameter.Value.Value; matrix[i, 1] = VelocityBoundsUpdater.StartValueParameter.Value.Value; } } } } #region Events protected override void OnProblemChanged() { UpdateAnalyzers(); ParameterizeAnalyzers(); base.OnProblemChanged(); } void TopologyInitializerParameter_ValueChanged(object sender, EventArgs e) { this.UpdateTopologyParameters(); } void VelocityBoundsUpdaterParameter_ValueChanged(object sender, EventArgs e) { if (VelocityBoundsParameter.Value != null) { foreach (IDiscreteDoubleMatrixModifier matrixOp in VelocityBoundsUpdaterParameter.Value.ScalingOperatorParameter.ValidValues) { matrixOp.ValueParameter.ActualName = VelocityBoundsUpdater.ScaleParameter.Name; matrixOp.StartValueParameter.Value = new DoubleValue(VelocityBoundsUpdater.ScaleParameter.ActualValue.Value); } } } #endregion #region Helpers private void Initialize() { TopologyInitializerParameter.ValueChanged += new EventHandler(TopologyInitializerParameter_ValueChanged); } private static void InitializeParticleCreator(CombinedOperator particleCreator) { Placeholder positionCreator = new Placeholder(); Assigner personalBestPositionAssigner = new Assigner(); UniformRandomRealVectorCreator velocityCreator = new UniformRandomRealVectorCreator(); particleCreator.Name = "Particle Creator"; particleCreator.OperatorGraph.InitialOperator = positionCreator; positionCreator.Name = "(SolutionCreator)"; positionCreator.OperatorParameter.ActualName = "SolutionCreator"; positionCreator.Successor = personalBestPositionAssigner; personalBestPositionAssigner.LeftSideParameter.ActualName = "PersonalBestPoint"; personalBestPositionAssigner.RightSideParameter.ActualName = "Point"; personalBestPositionAssigner.Successor = velocityCreator; velocityCreator.LengthParameter.ActualName = "ProblemSize"; velocityCreator.BoundsParameter.ActualName = "VelocityBounds"; velocityCreator.RealVectorParameter.ActualName = "Velocity"; } private void InitializeAnalyzers() { qualityAnalyzer = new BestAverageWorstQualityAnalyzer(); ParameterizeAnalyzers(); } private void ParameterizeAnalyzers() { if (Problem != null) { qualityAnalyzer.MaximizationParameter.ActualName = Problem.MaximizationParameter.Name; qualityAnalyzer.QualityParameter.ActualName = Problem.Evaluator.QualityParameter.ActualName; qualityAnalyzer.BestKnownQualityParameter.ActualName = Problem.BestKnownQualityParameter.Name; } } private void UpdateAnalyzers() { Analyzer.Operators.Clear(); if (Problem != null) { foreach (IAnalyzer analyzer in Problem.Operators.OfType()) Analyzer.Operators.Add(analyzer); } Analyzer.Operators.Add(qualityAnalyzer); } private void InitVelocityBoundsUpdater() { foreach (IDiscreteDoubleMatrixModifier matrixOp in ApplicationManager.Manager.GetInstances()) { VelocityBoundsUpdaterParameter.ValidValues.Add(matrixOp); matrixOp.ValueParameter.ActualName = VelocityBoundsParameter.Name; matrixOp.EndIndexParameter.ActualName = MaxIterationsParameter.Name; matrixOp.StartIndexParameter.Value = new IntValue(0); matrixOp.IndexParameter.ActualName = "CurrentIteration"; matrixOp.EndValueParameter.Value = new DoubleValue(0); } VelocityBoundsUpdaterParameter.ValueChanged += new EventHandler(VelocityBoundsUpdaterParameter_ValueChanged); } private void InitOmegaUpdater() { foreach (IDiscreteDoubleValueModifier updater in OmegaUpdaterParameter.ValidValues) { updater.EndIndexParameter.ActualName = MaxIterationsParameter.Name; updater.StartIndexParameter.Value = new IntValue(0); updater.IndexParameter.ActualName = "CurrentIteration"; updater.ValueParameter.ActualName = OmegaParameter.Name; updater.StartValueParameter.Value = new DoubleValue(1); updater.EndValueParameter.Value = new DoubleValue(0); } } private void UpdateOmegaUpdater() { IDiscreteDoubleValueModifier oldOmegaUpdater = OmegaUpdater; OmegaUpdaterParameter.ValidValues.Clear(); foreach (IDiscreteDoubleValueModifier updater in ApplicationManager.Manager.GetInstances().OrderBy(x => x.Name)) { OmegaUpdaterParameter.ValidValues.Add(updater); } if (oldOmegaUpdater != null) { IDiscreteDoubleValueModifier updater = OmegaUpdaterParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldOmegaUpdater.GetType()); if (updater != null) OmegaUpdaterParameter.Value = updater; } } private void UpdateTopologyInitializer() { ITopologyInitializer oldTopologyInitializer = TopologyInitializer; TopologyInitializerParameter.ValidValues.Clear(); foreach (ITopologyInitializer topologyInitializer in ApplicationManager.Manager.GetInstances().OrderBy(x => x.Name)) { TopologyInitializerParameter.ValidValues.Add(topologyInitializer); } if (oldTopologyInitializer != null && TopologyInitializerParameter.ValidValues.Any(x => x.GetType() == oldTopologyInitializer.GetType())) TopologyInitializer = TopologyInitializerParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldTopologyInitializer.GetType()); UpdateTopologyParameters(); } private void UpdateTopologyParameters() { ITopologyUpdater oldTopologyUpdater = TopologyUpdater; IParticleUpdater oldParticleUpdater = ParticleUpdater; ClearTopologyParameters(); if (TopologyInitializer != null) { foreach (ITopologyUpdater topologyUpdater in ApplicationManager.Manager.GetInstances()) TopologyUpdaterParameter.ValidValues.Add(topologyUpdater); foreach (IParticleUpdater particleUpdater in ApplicationManager.Manager.GetInstances()) ParticleUpdaterParameter.ValidValues.Add(particleUpdater); } else { foreach (IParticleUpdater particleUpdater in ApplicationManager.Manager.GetInstances()) ParticleUpdaterParameter.ValidValues.Add(particleUpdater); } if (oldTopologyUpdater != null) { ITopologyUpdater newTopologyUpdater = TopologyUpdaterParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldParticleUpdater.GetType()); if (newTopologyUpdater != null) TopologyUpdater = newTopologyUpdater; } if (oldParticleUpdater != null) { IParticleUpdater newParticleUpdater = ParticleUpdaterParameter.ValidValues.FirstOrDefault(x => x.GetType() == oldParticleUpdater.GetType()); if (newParticleUpdater != null) ParticleUpdater = newParticleUpdater; } } private void ClearTopologyParameters() { TopologyUpdaterParameter.ValidValues.Clear(); ParticleUpdaterParameter.ValidValues.Clear(); } #endregion } }