#region License Information
/* HeuristicLab
* Copyright (C) 2002-2010 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 class ParticleSwarmOptimization : EngineAlgorithm {
#region Problem Properties
public override Type ProblemType {
get { return typeof(ISingleObjectiveProblem); }
}
public new ISingleObjectiveProblem Problem {
get { return (ISingleObjectiveProblem)base.Problem; }
set { base.Problem = value; }
}
public MultiAnalyzer Analyzer {
get { return AnalyzerParameter.Value; }
set { AnalyzerParameter.Value = value; }
}
public ValueModifierSelector OmegaUpdater {
get { return OmegaUpdaterParameter.Value; }
set { OmegaUpdaterParameter.Value = value; }
}
public WeightedValueModifierSelector VelocityBoundsUpdater {
get { return VelocityBoundsUpdaterParameter.Value; }
set { VelocityBoundsUpdaterParameter.Value = value; }
}
#endregion
#region Parameter Properties
public ValueParameter SeedParameter {
get { return (ValueParameter)Parameters["Seed"]; }
}
public ValueParameter SetSeedRandomlyParameter {
get { return (ValueParameter)Parameters["SetSeedRandomly"]; }
}
public ValueParameter SwarmSizeParameter {
get { return (ValueParameter)Parameters["SwarmSize"]; }
}
public ValueParameter MaxIterationsParameter {
get { return (ValueParameter)Parameters["MaxIterations"]; }
}
public ValueParameter OmegaParameter {
get { return (ValueParameter)Parameters["Omega"]; }
}
public ValueParameter Phi_PParameter {
get { return (ValueParameter)Parameters["Phi_P"]; }
}
public ValueParameter Phi_GParameter {
get { return (ValueParameter)Parameters["Phi_G"]; }
}
public ValueParameter AnalyzerParameter {
get { return (ValueParameter)Parameters["Analyzer"]; }
}
public ValueLookupParameter VelocityBoundsParameter {
get { return (ValueLookupParameter)Parameters["VelocityBounds"]; }
}
public ConstrainedValueParameter ParticleUpdaterParameter {
get { return (ConstrainedValueParameter)Parameters["ParticleUpdater"]; }
}
public ConstrainedValueParameter TopologyInitializerParameter {
get { return (ConstrainedValueParameter)Parameters["TopologyInitializer"]; }
}
public ConstrainedValueParameter TopologyUpdaterParameter {
get { return (ConstrainedValueParameter)Parameters["TopologyUpdater"]; }
}
public ValueParameter VelocityBoundsUpdaterParameter {
get { return (ValueParameter)Parameters["VelocityBoundsUpdater"]; }
}
public ValueParameter OmegaUpdaterParameter {
get { return (ValueParameter)Parameters["OmegaUpdater"]; }
}
#endregion
#region Properties
[Storable]
private BestAverageWorstQualityAnalyzer qualityAnalyzer;
//[Storable]
//private IDiscreteDoubleValueModifier omegaModifier;
#endregion
[StorableConstructor]
protected ParticleSwarmOptimization(bool deserializing) : base(deserializing) { }
protected ParticleSwarmOptimization(ParticleSwarmOptimization original, Cloner cloner)
: base(original, cloner) {
qualityAnalyzer = cloner.Clone(original.qualityAnalyzer);
//omegaModifier = cloner.Clone(original.omegaModifier);
}
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",
new ItemSet(ApplicationManager.Manager.GetInstances())));
Parameters.Add(new ConstrainedValueParameter("TopologyInitializer", "Creates neighborhood description vectors",
new ItemSet(ApplicationManager.Manager.GetInstances())));
Parameters.Add(new ConstrainedValueParameter("TopologyUpdater", "Updates the neighborhood description vectors",
new ItemSet(ApplicationManager.Manager.GetInstances())));
//Parameters.Add(new ValueParameter("ParameterUpdater", "Updates the algorithm parameters according to some strategy",
// new MultiParameterUpdater()));
Parameters.Add(new ValueParameter("OmegaUpdater", "Updates the omega parameter", new ValueModifierSelector()));
Parameters.Add(new ValueParameter("VelocityBoundsUpdater", "Adjusts the velocity bounds", new WeightedValueModifierSelector()));
ParticleUpdaterParameter.ActualValue = ParticleUpdaterParameter.ValidValues.SingleOrDefault(v => v.GetType() == typeof(TotallyConnectedParticleUpdater));
TopologyInitializerParameter.ActualValue = TopologyInitializerParameter.ValidValues.SingleOrDefault(v => v.GetType() == typeof(EmptyTopologyInitializer));
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();
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 = topologyUpdaterPlaceholder;
particleUpdaterPlaceholder.Name = "(ParticleUpdater)";
particleUpdaterPlaceholder.OperatorParameter.ActualName = "ParticleUpdater";
particleUpdaterPlaceholder.Successor = evaluatorPlaceholder2;
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();
InitializeUpdaters();
UpdateAnalyzers();
}
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";
}
public override IDeepCloneable Clone(Cloner cloner) {
return new ParticleSwarmOptimization(this, cloner);
}
public override void Prepare() {
if (Problem != null) base.Prepare();
}
#region Events
protected override void OnProblemChanged() {
UpdateAnalyzers();
ParameterizeAnalyzers();
Problem.Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
base.OnProblemChanged();
}
#endregion
#region Helpers
private void InitializeParticleUpdaters() {
}
private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
}
private void InitializeAnalyzers() {
qualityAnalyzer = new BestAverageWorstQualityAnalyzer();
ParameterizeAnalyzers();
}
private void InitializeUpdaters() {
OmegaUpdater.ValueParameter.ActualName = OmegaParameter.Name;
foreach (IDiscreteDoubleValueModifier op in ApplicationManager.Manager.GetInstances()) {
OmegaUpdater.ModifierParameter.ValidValues.Add(op);
op.EndIndexParameter.ActualName = MaxIterationsParameter.Name;
op.StartIndexParameter.Value = new IntValue(0);
op.IndexParameter.ActualName = "CurrentIteration";
op.ValueParameter.ActualName = OmegaUpdater.ValueParameter.ActualName;
op.StartValueParameter.Value = new DoubleValue(OmegaParameter.Value.Value);
op.EndValueParameter.Value = new DoubleValue(-2);
}
VelocityBoundsUpdater.ValueParameter.ActualName = VelocityBoundsParameter.Name;
foreach (IDiscreteDoubleValueModifier op in ApplicationManager.Manager.GetInstances()) {
VelocityBoundsUpdater.ModifierParameter.ValidValues.Add(op);
op.EndIndexParameter.ActualName = MaxIterationsParameter.Name;
op.StartIndexParameter.Value = new IntValue(0);
op.IndexParameter.ActualName = "CurrentIteration";
op.ValueParameter.ActualName = VelocityBoundsUpdater.ScaleParameter.Name;
op.StartValueParameter.Value = new DoubleValue(VelocityBoundsUpdater.ScaleParameter.Value.Value);
op.EndValueParameter.Value = new DoubleValue(0);
}
}
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);
}
#endregion
}
}