QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
particleswarmoptimization.hpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4Copyright (C) 2015 Andres Hernandez
5
6This file is part of QuantLib, a free-software/open-source library
7for financial quantitative analysts and developers - http://quantlib.org/
8
9QuantLib is free software: you can redistribute it and/or modify it
10under the terms of the QuantLib license. You should have received a
11copy of the license along with this program; if not, please email
12<quantlib-dev@lists.sf.net>. The license is also available online at
13<http://quantlib.org/license.shtml>.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
27#ifndef quantlib_optimization_particleswarmoptimization_hpp
28#define quantlib_optimization_particleswarmoptimization_hpp
29
30#include <ql/math/optimization/problem.hpp>
31#include <ql/math/optimization/constraint.hpp>
32#include <ql/math/randomnumbers/mt19937uniformrng.hpp>
33#include <ql/experimental/math/isotropicrandomwalk.hpp>
34#include <ql/experimental/math/levyflightdistribution.hpp>
35#include <ql/math/randomnumbers/seedgenerator.hpp>
36
37#include <random>
38
39namespace QuantLib {
40
93 public:
94 class Inertia;
95 class Topology;
97 ext::shared_ptr<Topology> topology,
98 ext::shared_ptr<Inertia> inertia,
99 Real c1 = 2.05,
100 Real c2 = 2.05,
101 unsigned long seed = SeedGenerator::instance().get());
103 ext::shared_ptr<Topology> topology,
104 ext::shared_ptr<Inertia> inertia,
105 Real omega,
106 Real c1,
107 Real c2,
108 unsigned long seed = SeedGenerator::instance().get());
109 void startState(Problem &P, const EndCriteria &endCriteria);
110 EndCriteria::Type minimize(Problem& P, const EndCriteria& endCriteria) override;
111
112 protected:
113 std::vector<Array> X_, V_, pBX_, gBX_;
119 ext::shared_ptr<Topology> topology_;
120 ext::shared_ptr<Inertia> inertia_;
121 };
122
124
129 public:
130 virtual ~Inertia() = default;
132 virtual void setSize(Size M, Size N, Real c0, const EndCriteria &endCriteria) = 0;
134 virtual void setValues() = 0;
135 protected:
137 std::vector<Array> *X_, *V_, *pBX_, *gBX_;
140
141 virtual void init(ParticleSwarmOptimization *pso) {
142 pso_ = pso;
143 X_ = &pso_->X_;
144 V_ = &pso_->V_;
145 pBX_ = &pso_->pBX_;
146 gBX_ = &pso_->gBX_;
147 pBF_ = &pso_->pBF_;
148 gBF_ = &pso_->gBF_;
149 lX_ = &pso_->lX_;
150 uX_ = &pso_->uX_;
151 }
152 };
153
155 /* Inertia is a static value
156 */
158 public:
159 inline void setSize(Size M, Size N, Real c0, const EndCriteria& endCriteria) override {
160 c0_ = c0;
161 M_ = M;
162 }
163 inline void setValues() override {
164 for (Size i = 0; i < M_; i++) {
165 (*V_)[i] *= c0_;
166 }
167 }
168
169 private:
172 };
173
175 /* Inertia value gets multiplied with a random number
176 between (threshold, 1)
177 */
179 public:
180 SimpleRandomInertia(Real threshold = 0.5, unsigned long seed = SeedGenerator::instance().get())
181 : threshold_(threshold), rng_(seed) {
182 QL_REQUIRE(threshold_ >= 0.0 && threshold_ < 1.0, "Threshold must be a Real in [0, 1)");
183 }
184 inline void setSize(Size M, Size N, Real c0, const EndCriteria& endCriteria) override {
185 M_ = M;
186 c0_ = c0;
187 }
188 inline void setValues() override {
189 for (Size i = 0; i < M_; i++) {
190 Real val = c0_*(threshold_ + (1.0 - threshold_)*rng_.nextReal());
191 (*V_)[i] *= val;
192 }
193 }
194
195 private:
199 };
200
202 /* Inertia value gets decreased every iteration until it reaches
203 a value of threshold when iteration reaches the maximum level
204 */
206 public:
207 DecreasingInertia(Real threshold = 0.5)
208 : threshold_(threshold) {
209 QL_REQUIRE(threshold_ >= 0.0 && threshold_ < 1.0, "Threshold must be a Real in [0, 1)");
210 }
211 inline void setSize(Size M, Size N, Real c0, const EndCriteria& endCriteria) override {
212 N_ = N;
213 c0_ = c0;
214 iteration_ = 0;
215 maxIterations_ = endCriteria.maxIterations();
216 }
217 inline void setValues() override {
219 for (Size i = 0; i < M_; i++) {
220 (*V_)[i] *= c0;
221 }
222 }
223
224 private:
227 };
228
230 /* Alen Lukic, Approximating Kinetic Parameters Using Particle
231 Swarm Optimization.
232 */
234 public:
235 AdaptiveInertia(Real minInertia, Real maxInertia, Size sh = 5, Size sl = 2)
236 :minInertia_(minInertia), maxInertia_(maxInertia),
237 sh_(sh), sl_(sl) {};
238 inline void setSize(Size M, Size N, Real c0, const EndCriteria& endCriteria) override {
239 M_ = M;
240 c0_ = c0;
241 adaptiveCounter = 0;
243 started_ = false;
244 }
245 void setValues() override;
246
247 private:
254 };
255
257 /* As long as the particle keeps getting frequent updates to its
258 personal best value, the inertia behaves like a SimpleRandomInertia,
259 but after a number of iterations without improvement, the behaviour
260 changes to that of a Levy flight ~ u^{-1/\alpha}
261 */
263 public:
264 LevyFlightInertia(Real alpha, Size threshold,
265 unsigned long seed = SeedGenerator::instance().get())
266 :rng_(seed), generator_(seed), flight_(generator_, LevyFlightDistribution(1.0, alpha),
267 1, Array(1, 1.0), seed),
268 threshold_(threshold) {};
269 inline void setSize(Size M, Size N, Real c0, const EndCriteria& endCriteria) override {
270 M_ = M;
271 N_ = N;
272 c0_ = c0;
273 adaptiveCounter_ = std::vector<Size>(M_, 0);
274 }
275 inline void setValues() override {
276 for (Size i = 0; i < M_; i++) {
277 if ((*pBF_)[i] < personalBestF_[i]) {
278 personalBestF_[i] = (*pBF_)[i];
279 adaptiveCounter_[i] = 0;
280 }
281 else {
282 adaptiveCounter_[i]++;
283 }
284 if (adaptiveCounter_[i] <= threshold_) {
285 //Simple Random Inertia
286 (*V_)[i] *= c0_*(0.5 + 0.5*rng_.nextReal());
287 }
288 else {
289 //If particle has not found a new personal best after threshold_ iterations
290 //then trigger a Levy flight pattern for the speed
291 flight_.nextReal<Real *>(&(*V_)[i][0]);
292 }
293 }
294 }
295
296 protected:
297 void init(ParticleSwarmOptimization* pso) override {
300 flight_.setDimension(N_, *lX_, *uX_);
301 }
302
303 private:
305 std::mt19937 generator_;
308 std::vector<Size> adaptiveCounter_;
312 };
313
315
320 public:
321 virtual ~Topology() = default;
323 virtual void setSize(Size M) = 0;
325 virtual void findSocialBest() = 0;
326 protected:
328 std::vector<Array> *X_, *V_, *pBX_, *gBX_;
330 private:
332 pso_ = pso;
333 X_ = &pso_->X_;
334 V_ = &pso_->V_;
335 pBX_ = &pso_->pBX_;
336 gBX_ = &pso_->gBX_;
337 pBF_ = &pso_->pBF_;
338 gBF_ = &pso_->gBF_;
339 }
340 };
341
343 /* The global best as seen by each particle is the best from amongst
344 all particles
345 */
347 public:
348 inline void setSize(Size M) override { M_ = M; }
349 inline void findSocialBest() override {
350 Real bestF = (*pBF_)[0];
351 Size bestP = 0;
352 for (Size i = 1; i < M_; i++) {
353 if (bestF < (*pBF_)[i]) {
354 bestF = (*pBF_)[i];
355 bestP = i;
356 }
357 }
358 Array& x = (*pBX_)[bestP];
359 for (Size i = 0; i < M_; i++) {
360 if (i != bestP) {
361 (*gBX_)[i] = x;
362 (*gBF_)[i] = bestF;
363 }
364 }
365 }
366
367 private:
369 };
370
372 /* The global best as seen by each particle is the best from amongst
373 the previous K and next K neighbors. For particle I, the best is
374 then taken from amongst the [I - K, I + K] particles.
375 */
377 public:
378 KNeighbors(Size K = 1) :K_(K) {
379 QL_REQUIRE(K > 0, "Neighbors need to be larger than 0");
380 }
381 inline void setSize(Size M) override {
382 M_ = M;
383 QL_ENSURE(K_ < M, "Number of neighbors need to be smaller than total particles in swarm");
384 }
385 void findSocialBest() override;
386
387 private:
389 };
390
392 /* H.M. Emara, Adaptive Clubs-based Particle Swarm Optimization
393 Each particle is originally assigned to a default number of clubs
394 from among the total set. The best as seen by each particle is the
395 best from amongst the clubs to which the particle belongs.
396 Underperforming particles join more clubs randomly (up to a maximum
397 number) to widen the particles that influence them, while
398 overperforming particles leave clubs randomly (down to a minimum
399 number) to avoid early convergence to local minima.
400 */
402 public:
403 ClubsTopology(Size defaultClubs, Size totalClubs,
404 Size maxClubs, Size minClubs,
405 Size resetIteration, unsigned long seed = SeedGenerator::instance().get());
406 void setSize(Size M) override;
407 void findSocialBest() override;
408
409 private:
413 std::vector<std::vector<bool> > clubs4particles_;
414 std::vector<std::vector<bool> > particles4clubs_;
415 std::vector<Size> bestByClub_;
416 std::vector<Size> worstByClub_;
417 std::mt19937 generator_;
418 std::uniform_int_distribution<QuantLib::Size> distribution_;
420
421 void leaveRandomClub(Size particle, Size currentClubs);
422 void joinRandomClub(Size particle, Size currentClubs);
423 };
424
425}
426
427#endif
void setValues() override
produce changes to PSO state for current iteration
void setSize(Size M, Size N, Real c0, const EndCriteria &endCriteria) override
initialize state for current problem
AdaptiveInertia(Real minInertia, Real maxInertia, Size sh=5, Size sl=2)
1-D array used in linear algebra.
Definition: array.hpp:52
std::uniform_int_distribution< QuantLib::Size > distribution_
std::vector< std::vector< bool > > particles4clubs_
std::vector< std::vector< bool > > clubs4particles_
void setSize(Size M) override
initialize state for current problem
decltype(distribution_)::param_type param_type
void findSocialBest() override
produce changes to PSO state for current iteration
void joinRandomClub(Size particle, Size currentClubs)
void leaveRandomClub(Size particle, Size currentClubs)
void setValues() override
produce changes to PSO state for current iteration
void setSize(Size M, Size N, Real c0, const EndCriteria &endCriteria) override
initialize state for current problem
Criteria to end optimization process:
Definition: endcriteria.hpp:40
Size maxIterations() const
void setSize(Size M) override
initialize state for current problem
void findSocialBest() override
produce changes to PSO state for current iteration
void setSize(Size M) override
initialize state for current problem
void findSocialBest() override
produce changes to PSO state for current iteration
void setValues() override
produce changes to PSO state for current iteration
IsotropicRandomWalk< LevyFlightDistribution, std::mt19937 > flight_
LevyFlightInertia(Real alpha, Size threshold, unsigned long seed=SeedGenerator::instance().get())
void setSize(Size M, Size N, Real c0, const EndCriteria &endCriteria) override
initialize state for current problem
void init(ParticleSwarmOptimization *pso) override
Uniform random number generator.
Real nextReal() const
return a random number in the (0.0, 1.0)-interval
Abstract class for constrained optimization method.
Definition: method.hpp:36
Base inertia class used to alter the PSO state.
virtual void setSize(Size M, Size N, Real c0, const EndCriteria &endCriteria)=0
initialize state for current problem
virtual void init(ParticleSwarmOptimization *pso)
virtual void setValues()=0
produce changes to PSO state for current iteration
Base topology class used to determine the personal and global best.
virtual void setSize(Size M)=0
initialize state for current problem
virtual void findSocialBest()=0
produce changes to PSO state for current iteration
void startState(Problem &P, const EndCriteria &endCriteria)
EndCriteria::Type minimize(Problem &P, const EndCriteria &endCriteria) override
minimize the optimization problem P
Constrained optimization problem.
Definition: problem.hpp:42
void setValues() override
produce changes to PSO state for current iteration
SimpleRandomInertia(Real threshold=0.5, unsigned long seed=SeedGenerator::instance().get())
void setSize(Size M, Size N, Real c0, const EndCriteria &endCriteria) override
initialize state for current problem
static SeedGenerator & instance()
access to the unique instance
Definition: singleton.hpp:104
void setValues() override
produce changes to PSO state for current iteration
void setSize(Size M, Size N, Real c0, const EndCriteria &endCriteria) override
initialize state for current problem
#define QL_MAX_REAL
Definition: qldefines.hpp:176
QL_REAL Real
real number
Definition: types.hpp:50
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35