1
#region License Information
3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 * This file is part of HeuristicLab.
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
24 using HeuristicLab
.Analysis
;
25 using HeuristicLab
.Common
;
26 using HeuristicLab
.Core
;
27 using HeuristicLab
.Data
;
28 using HeuristicLab
.Operators
;
29 using HeuristicLab
.Optimization
;
30 using HeuristicLab
.Optimization
.Operators
;
31 using HeuristicLab
.Parameters
;
32 using HeuristicLab
.Persistence
.Default
.CompositeSerializers
.Storable
;
33 using HeuristicLab
.PluginInfrastructure
;
34 using HeuristicLab
.Random
;
36 namespace HeuristicLab
.Algorithms
.ParticleSwarmOptimization
{
37 [Item("Particle Swarm Optimization", "A particle swarm optimization algorithm based on the description in Pedersen, M.E.H. (2010). PhD thesis. University of Southampton.")]
38 [Creatable("Algorithms")]
40 public sealed class ParticleSwarmOptimization
: HeuristicOptimizationEngineAlgorithm
, IStorableContent
{
41 #region Parameter Properties
42 public IValueParameter
<IntValue
> SeedParameter
{
43 get { return (IValueParameter<IntValue>)Parameters["Seed"]; }
45 public IValueParameter
<BoolValue
> SetSeedRandomlyParameter
{
46 get { return (IValueParameter<BoolValue>)Parameters["SetSeedRandomly"]; }
48 public IValueParameter
<IntValue
> SwarmSizeParameter
{
49 get { return (IValueParameter<IntValue>)Parameters["SwarmSize"]; }
51 public IValueParameter
<IntValue
> MaxIterationsParameter
{
52 get { return (IValueParameter<IntValue>)Parameters["MaxIterations"]; }
54 public IValueParameter
<DoubleValue
> InertiaParameter
{
55 get { return (IValueParameter<DoubleValue>)Parameters["Inertia"]; }
57 public IValueParameter
<DoubleValue
> PersonalBestAttractionParameter
{
58 get { return (IValueParameter<DoubleValue>)Parameters["PersonalBestAttraction"]; }
60 public IValueParameter
<DoubleValue
> NeighborBestAttractionParameter
{
61 get { return (IValueParameter<DoubleValue>)Parameters["NeighborBestAttraction"]; }
63 public IValueParameter
<MultiAnalyzer
> AnalyzerParameter
{
64 get { return (IValueParameter<MultiAnalyzer>)Parameters["Analyzer"]; }
66 public ConstrainedValueParameter
<IParticleCreator
> ParticleCreatorParameter
{
67 get { return (ConstrainedValueParameter<IParticleCreator>)Parameters["ParticleCreator"]; }
69 public ConstrainedValueParameter
<IParticleUpdater
> ParticleUpdaterParameter
{
70 get { return (ConstrainedValueParameter<IParticleUpdater>)Parameters["ParticleUpdater"]; }
72 public OptionalConstrainedValueParameter
<ITopologyInitializer
> TopologyInitializerParameter
{
73 get { return (OptionalConstrainedValueParameter<ITopologyInitializer>)Parameters["TopologyInitializer"]; }
75 public OptionalConstrainedValueParameter
<ITopologyUpdater
> TopologyUpdaterParameter
{
76 get { return (OptionalConstrainedValueParameter<ITopologyUpdater>)Parameters["TopologyUpdater"]; }
78 public OptionalConstrainedValueParameter
<IDiscreteDoubleValueModifier
> InertiaUpdaterParameter
{
79 get { return (OptionalConstrainedValueParameter<IDiscreteDoubleValueModifier>)Parameters["InertiaUpdater"]; }
81 public ConstrainedValueParameter
<ISwarmUpdater
> SwarmUpdaterParameter
{
82 get { return (ConstrainedValueParameter<ISwarmUpdater>)Parameters["SwarmUpdater"]; }
89 public string Filename { get; set; }
92 private BestAverageWorstQualityAnalyzer qualityAnalyzer
;
95 private SolutionsCreator solutionsCreator
;
98 private ParticleSwarmOptimizationMainLoop mainLoop
;
100 public override Type ProblemType
{
101 get { return typeof(ISingleObjectiveHeuristicOptimizationProblem); }
103 public new ISingleObjectiveHeuristicOptimizationProblem Problem
{
104 get { return (ISingleObjectiveHeuristicOptimizationProblem)base.Problem; }
105 set { base.Problem = value; }
107 public IntValue Seed
{
108 get { return SeedParameter.Value; }
109 set { SeedParameter.Value = value; }
111 public BoolValue SetSeedRandomly
{
112 get { return SetSeedRandomlyParameter.Value; }
113 set { SetSeedRandomlyParameter.Value = value; }
115 public IntValue SwarmSize
{
116 get { return SwarmSizeParameter.Value; }
117 set { SwarmSizeParameter.Value = value; }
119 public IntValue MaxIterations
{
120 get { return MaxIterationsParameter.Value; }
121 set { MaxIterationsParameter.Value = value; }
123 public DoubleValue Inertia
{
124 get { return InertiaParameter.Value; }
125 set { InertiaParameter.Value = value; }
127 public DoubleValue PersonalBestAttraction
{
128 get { return PersonalBestAttractionParameter.Value; }
129 set { PersonalBestAttractionParameter.Value = value; }
131 public DoubleValue NeighborBestAttraction
{
132 get { return NeighborBestAttractionParameter.Value; }
133 set { NeighborBestAttractionParameter.Value = value; }
135 public MultiAnalyzer Analyzer
{
136 get { return AnalyzerParameter.Value; }
137 set { AnalyzerParameter.Value = value; }
139 public IParticleCreator ParticleCreator
{
140 get { return ParticleCreatorParameter.Value; }
141 set { ParticleCreatorParameter.Value = value; }
143 public IParticleUpdater ParticleUpdater
{
144 get { return ParticleUpdaterParameter.Value; }
145 set { ParticleUpdaterParameter.Value = value; }
147 public ITopologyInitializer TopologyInitializer
{
148 get { return TopologyInitializerParameter.Value; }
149 set { TopologyInitializerParameter.Value = value; }
151 public ITopologyUpdater TopologyUpdater
{
152 get { return TopologyUpdaterParameter.Value; }
153 set { TopologyUpdaterParameter.Value = value; }
155 public IDiscreteDoubleValueModifier InertiaUpdater
{
156 get { return InertiaUpdaterParameter.Value; }
157 set { InertiaUpdaterParameter.Value = value; }
159 public ISwarmUpdater SwarmUpdater
{
160 get { return SwarmUpdaterParameter.Value; }
161 set { SwarmUpdaterParameter.Value = value; }
165 [StorableConstructor
]
166 private ParticleSwarmOptimization(bool deserializing
) : base(deserializing
) { }
167 private ParticleSwarmOptimization(ParticleSwarmOptimization original
, Cloner cloner
)
168 : base(original
, cloner
) {
169 qualityAnalyzer
= cloner
.Clone(original
.qualityAnalyzer
);
170 solutionsCreator
= cloner
.Clone(original
.solutionsCreator
);
171 mainLoop
= cloner
.Clone(original
.mainLoop
);
174 public ParticleSwarmOptimization()
176 Parameters
.Add(new ValueParameter
<IntValue
>("Seed", "The random seed used to initialize the new pseudo random number generator.", new IntValue(0)));
177 Parameters
.Add(new ValueParameter
<BoolValue
>("SetSeedRandomly", "True if the random seed should be set to a random value, otherwise false.", new BoolValue(true)));
178 Parameters
.Add(new ValueParameter
<IntValue
>("SwarmSize", "Size of the particle swarm.", new IntValue(10)));
179 Parameters
.Add(new ValueParameter
<IntValue
>("MaxIterations", "Maximal number of iterations.", new IntValue(1000)));
180 Parameters
.Add(new ValueParameter
<MultiAnalyzer
>("Analyzer", "The operator used to analyze each generation.", new MultiAnalyzer()));
181 Parameters
.Add(new ValueParameter
<DoubleValue
>("Inertia", "Inertia weight on a particle's movement (omega).", new DoubleValue(1)));
182 Parameters
.Add(new ValueParameter
<DoubleValue
>("PersonalBestAttraction", "Weight for particle's pull towards its personal best soution (phi_p).", new DoubleValue(-0.01)));
183 Parameters
.Add(new ValueParameter
<DoubleValue
>("NeighborBestAttraction", "Weight for pull towards the neighborhood best solution or global best solution in case of a totally connected topology (phi_g).", new DoubleValue(3.7)));
184 Parameters
.Add(new ConstrainedValueParameter
<IParticleCreator
>("ParticleCreator", "Operator that creates a new particle."));
185 Parameters
.Add(new ConstrainedValueParameter
<IParticleUpdater
>("ParticleUpdater", "Operator that updates a particle."));
186 Parameters
.Add(new OptionalConstrainedValueParameter
<ITopologyInitializer
>("TopologyInitializer", "Creates neighborhood description vectors."));
187 Parameters
.Add(new OptionalConstrainedValueParameter
<ITopologyUpdater
>("TopologyUpdater", "Updates the neighborhood description vectors."));
188 Parameters
.Add(new OptionalConstrainedValueParameter
<IDiscreteDoubleValueModifier
>("InertiaUpdater", "Updates the omega parameter."));
189 Parameters
.Add(new ConstrainedValueParameter
<ISwarmUpdater
>("SwarmUpdater", "Encoding-specific parameter which is provided by the problem. May provide additional encoding-specific parameters, such as velocity bounds for real valued problems"));
190 ParticleUpdaterParameter
.Hidden
= true;
192 RandomCreator randomCreator
= new RandomCreator();
193 VariableCreator variableCreator
= new VariableCreator();
194 Assigner currentInertiaAssigner
= new Assigner();
195 solutionsCreator
= new SolutionsCreator();
196 SubScopesCounter subScopesCounter
= new SubScopesCounter();
197 Placeholder topologyInitializerPlaceholder
= new Placeholder();
198 mainLoop
= new ParticleSwarmOptimizationMainLoop();
200 OperatorGraph
.InitialOperator
= randomCreator
;
202 randomCreator
.SetSeedRandomlyParameter
.Value
= null;
203 randomCreator
.SeedParameter
.Value
= null;
204 randomCreator
.Successor
= variableCreator
;
206 variableCreator
.CollectedValues
.Add(new ValueParameter
<IntValue
>("Iterations", new IntValue(0)));
207 variableCreator
.Successor
= currentInertiaAssigner
;
209 currentInertiaAssigner
.Name
= "CurrentInertia := Inertia";
210 currentInertiaAssigner
.LeftSideParameter
.ActualName
= "CurrentInertia";
211 currentInertiaAssigner
.RightSideParameter
.ActualName
= "Inertia";
212 currentInertiaAssigner
.Successor
= solutionsCreator
;
214 solutionsCreator
.NumberOfSolutionsParameter
.ActualName
= "SwarmSize";
215 ParameterizeSolutionsCreator();
216 solutionsCreator
.Successor
= subScopesCounter
;
218 subScopesCounter
.Name
= "Initialize EvaluatedSolutions";
219 subScopesCounter
.ValueParameter
.ActualName
= "EvaluatedSolutions";
220 subScopesCounter
.Successor
= topologyInitializerPlaceholder
;
222 topologyInitializerPlaceholder
.Name
= "(TopologyInitializer)";
223 topologyInitializerPlaceholder
.OperatorParameter
.ActualName
= "TopologyInitializer";
224 topologyInitializerPlaceholder
.Successor
= mainLoop
;
226 mainLoop
.AnalyzerParameter
.ActualName
= AnalyzerParameter
.Name
;
227 mainLoop
.InertiaParameter
.ActualName
= "CurrentInertia";
228 mainLoop
.MaxIterationsParameter
.ActualName
= MaxIterationsParameter
.Name
;
229 mainLoop
.NeighborBestAttractionParameter
.ActualName
= NeighborBestAttractionParameter
.Name
;
230 mainLoop
.InertiaUpdaterParameter
.ActualName
= InertiaUpdaterParameter
.Name
;
231 mainLoop
.ParticleUpdaterParameter
.ActualName
= ParticleUpdaterParameter
.Name
;
232 mainLoop
.PersonalBestAttractionParameter
.ActualName
= PersonalBestAttractionParameter
.Name
;
233 mainLoop
.RandomParameter
.ActualName
= randomCreator
.RandomParameter
.ActualName
;
234 mainLoop
.SwarmSizeParameter
.ActualName
= SwarmSizeParameter
.Name
;
235 mainLoop
.TopologyUpdaterParameter
.ActualName
= TopologyUpdaterParameter
.Name
;
236 mainLoop
.RandomParameter
.ActualName
= randomCreator
.RandomParameter
.ActualName
;
237 mainLoop
.ResultsParameter
.ActualName
= "Results";
239 InitializeAnalyzers();
240 InitializeParticleCreator();
241 InitializeSwarmUpdater();
242 ParameterizeSolutionsCreator();
244 UpdateInertiaUpdater();
245 InitInertiaUpdater();
246 UpdateTopologyInitializer();
248 ParameterizeMainLoop();
251 public override IDeepCloneable
Clone(Cloner cloner
) {
252 return new ParticleSwarmOptimization(this, cloner
);
255 [StorableHook(HookType
.AfterDeserialization
)]
256 private void AfterDeserialization() {
260 public override void Prepare() {
261 if (Problem
!= null && ParticleCreator
!= null && ParticleUpdater
!= null) {
267 protected override void OnProblemChanged() {
269 ParameterizeAnalyzers();
270 UpdateTopologyParameters();
271 InitializeParticleCreator();
272 InitializeSwarmUpdater();
273 ParameterizeSolutionsCreator();
274 base.OnProblemChanged();
277 void TopologyInitializerParameter_ValueChanged(object sender
, EventArgs e
) {
278 this.UpdateTopologyParameters();
283 private void Initialize() {
284 TopologyInitializerParameter
.ValueChanged
+= new EventHandler(TopologyInitializerParameter_ValueChanged
);
287 private void InitializeParticleCreator() {
288 if (Problem
!= null) {
289 IParticleCreator oldParticleCreator
= ParticleCreator
;
290 ParticleCreatorParameter
.ValidValues
.Clear();
291 foreach (IParticleCreator Creator
in Problem
.Operators
.OfType
<IParticleCreator
>().OrderBy(x
=> x
.Name
)) {
292 ParticleCreatorParameter
.ValidValues
.Add(Creator
);
294 if (oldParticleCreator
!= null) {
295 IParticleCreator creator
= ParticleCreatorParameter
.ValidValues
.FirstOrDefault(x
=> x
.GetType() == oldParticleCreator
.GetType());
296 if (creator
!= null) ParticleCreator
= creator
;
301 private void InitializeAnalyzers() {
302 qualityAnalyzer
= new BestAverageWorstQualityAnalyzer();
303 qualityAnalyzer
.ResultsParameter
.ActualName
= "Results";
304 ParameterizeAnalyzers();
307 private void ParameterizeAnalyzers() {
308 if (Problem
!= null) {
309 qualityAnalyzer
.MaximizationParameter
.ActualName
= Problem
.MaximizationParameter
.Name
;
310 qualityAnalyzer
.QualityParameter
.ActualName
= Problem
.Evaluator
.QualityParameter
.ActualName
;
311 qualityAnalyzer
.BestKnownQualityParameter
.ActualName
= Problem
.BestKnownQualityParameter
.Name
;
315 private void UpdateAnalyzers() {
316 Analyzer
.Operators
.Clear();
317 if (Problem
!= null) {
318 foreach (IAnalyzer analyzer
in Problem
.Operators
.OfType
<IAnalyzer
>())
319 Analyzer
.Operators
.Add(analyzer
);
321 Analyzer
.Operators
.Add(qualityAnalyzer
);
324 private void InitInertiaUpdater() {
325 foreach (IDiscreteDoubleValueModifier updater
in InertiaUpdaterParameter
.ValidValues
) {
326 updater
.EndIndexParameter
.ActualName
= MaxIterationsParameter
.Name
;
327 updater
.EndIndexParameter
.Hidden
= true;
328 updater
.StartIndexParameter
.Value
= new IntValue(0);
329 updater
.StartIndexParameter
.Hidden
= true;
330 updater
.IndexParameter
.ActualName
= "Iterations";
331 updater
.ValueParameter
.ActualName
= "CurrentInertia";
332 updater
.StartValueParameter
.Value
= new DoubleValue(1);
333 updater
.EndValueParameter
.Value
= new DoubleValue(1E-10);
337 private void UpdateInertiaUpdater() {
338 IDiscreteDoubleValueModifier oldInertiaUpdater
= InertiaUpdater
;
339 InertiaUpdaterParameter
.ValidValues
.Clear();
340 foreach (IDiscreteDoubleValueModifier updater
in ApplicationManager
.Manager
.GetInstances
<IDiscreteDoubleValueModifier
>().OrderBy(x
=> x
.Name
)) {
341 InertiaUpdaterParameter
.ValidValues
.Add(updater
);
343 if (oldInertiaUpdater
!= null) {
344 IDiscreteDoubleValueModifier updater
= InertiaUpdaterParameter
.ValidValues
.FirstOrDefault(x
=> x
.GetType() == oldInertiaUpdater
.GetType());
345 if (updater
!= null) InertiaUpdaterParameter
.Value
= updater
;
349 private void UpdateTopologyInitializer() {
350 ITopologyInitializer oldTopologyInitializer
= TopologyInitializer
;
351 TopologyInitializerParameter
.ValidValues
.Clear();
352 foreach (ITopologyInitializer topologyInitializer
in ApplicationManager
.Manager
.GetInstances
<ITopologyInitializer
>().OrderBy(x
=> x
.Name
)) {
353 TopologyInitializerParameter
.ValidValues
.Add(topologyInitializer
);
355 if (oldTopologyInitializer
!= null && TopologyInitializerParameter
.ValidValues
.Any(x
=> x
.GetType() == oldTopologyInitializer
.GetType()))
356 TopologyInitializer
= TopologyInitializerParameter
.ValidValues
.FirstOrDefault(x
=> x
.GetType() == oldTopologyInitializer
.GetType());
357 UpdateTopologyParameters();
360 private void ParameterizeTopologyUpdaters() {
361 foreach (var updater
in TopologyUpdaterParameter
.ValidValues
) {
362 var multiPsoUpdater
= updater
as MultiPSOTopologyUpdater
;
363 if (multiPsoUpdater
!= null) {
364 multiPsoUpdater
.CurrentIterationParameter
.ActualName
= "Iterations";
369 private void UpdateTopologyParameters() {
370 ITopologyUpdater oldTopologyUpdater
= TopologyUpdater
;
371 IParticleUpdater oldParticleUpdater
= ParticleUpdater
;
372 ClearTopologyParameters();
373 if (Problem
!= null) {
374 if (TopologyInitializer
!= null) {
375 foreach (ITopologyUpdater topologyUpdater
in ApplicationManager
.Manager
.GetInstances
<ITopologyUpdater
>())
376 TopologyUpdaterParameter
.ValidValues
.Add(topologyUpdater
);
377 foreach (IParticleUpdater particleUpdater
in Problem
.Operators
.OfType
<ILocalParticleUpdater
>().OrderBy(x
=> x
.Name
))
378 ParticleUpdaterParameter
.ValidValues
.Add(particleUpdater
);
380 foreach (IParticleUpdater particleUpdater
in Problem
.Operators
.OfType
<IGlobalParticleUpdater
>().OrderBy(x
=> x
.Name
))
381 ParticleUpdaterParameter
.ValidValues
.Add(particleUpdater
);
383 if (oldTopologyUpdater
!= null) {
384 ITopologyUpdater newTopologyUpdater
= TopologyUpdaterParameter
.ValidValues
.FirstOrDefault(x
=> x
.GetType() == oldParticleUpdater
.GetType());
385 if (newTopologyUpdater
!= null) TopologyUpdater
= newTopologyUpdater
;
387 if (oldParticleUpdater
!= null) {
388 IParticleUpdater newParticleUpdater
= ParticleUpdaterParameter
.ValidValues
.FirstOrDefault(x
=> x
.GetType() == oldParticleUpdater
.GetType());
389 if (newParticleUpdater
!= null) ParticleUpdater
= newParticleUpdater
;
392 ParameterizeTopologyUpdaters();
396 private void ClearTopologyParameters() {
397 TopologyUpdaterParameter
.ValidValues
.Clear();
398 ParticleUpdaterParameter
.ValidValues
.Clear();
401 private void ParameterizeSolutionsCreator() {
402 if (Problem
!= null) {
403 solutionsCreator
.EvaluatorParameter
.ActualName
= Problem
.EvaluatorParameter
.Name
;
404 solutionsCreator
.SolutionCreatorParameter
.ActualName
= ParticleCreatorParameter
.Name
;
408 private void ParameterizeMainLoop() {
409 if (Problem
!= null) {
410 mainLoop
.EvaluatorParameter
.ActualName
= Problem
.EvaluatorParameter
.Name
;
414 private void InitializeSwarmUpdater() {
415 if (Problem
!= null) {
416 ISwarmUpdater updater
= Problem
.Operators
.OfType
<ISwarmUpdater
>().FirstOrDefault();
417 SwarmUpdaterParameter
.ValidValues
.Clear();
418 if (updater
!= null) {
419 SwarmUpdaterParameter
.ValidValues
.Add(updater
);
420 SwarmUpdaterParameter
.Value
= updater
;