1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
19 Particle(size_t nDimensionality
)
20 : mVelocity(nDimensionality
)
21 , mPosition(nDimensionality
)
22 , mCurrentFitness(std::numeric_limits
<float>::lowest())
23 , mBestPosition(nDimensionality
)
24 , mBestFitness(std::numeric_limits
<float>::lowest())
28 std::vector
<double> mVelocity
;
30 std::vector
<double> mPosition
;
31 double mCurrentFitness
;
33 std::vector
<double> mBestPosition
;
37 template <typename DataProvider
> class ParticleSwarmOptimizationAlgorithm
41 static constexpr double constWeight
= 0.729;
42 // cognitive coefficient
43 static constexpr double c1
= 1.49445;
45 static constexpr double c2
= 1.49445;
47 static constexpr double constAcceptedPrecision
= 0.000000001;
49 DataProvider
& mrDataProvider
;
51 size_t mnNumOfParticles
;
53 std::vector
<Particle
> maSwarm
;
55 std::random_device maRandomDevice
;
56 std::mt19937 maGenerator
;
57 size_t mnDimensionality
;
59 std::uniform_real_distribution
<> maRandom01
;
61 std::vector
<double> maBestPosition
;
67 ParticleSwarmOptimizationAlgorithm(DataProvider
& rDataProvider
, size_t nNumOfParticles
)
68 : mrDataProvider(rDataProvider
)
69 , mnNumOfParticles(nNumOfParticles
)
70 , maGenerator(maRandomDevice())
71 , mnDimensionality(mrDataProvider
.getDimensionality())
72 , maRandom01(0.0, 1.0)
73 , maBestPosition(mnDimensionality
)
74 , mfBestFitness(std::numeric_limits
<float>::lowest())
80 std::vector
<double> const& getResult() { return maBestPosition
; }
82 int getGeneration() { return mnGeneration
; }
84 int getLastChange() { return mnLastChange
; }
92 mfBestFitness
= std::numeric_limits
<float>::lowest();
94 maSwarm
.reserve(mnNumOfParticles
);
95 for (size_t i
= 0; i
< mnNumOfParticles
; i
++)
97 maSwarm
.emplace_back(mnDimensionality
);
98 Particle
& rParticle
= maSwarm
.back();
100 mrDataProvider
.initializeVariables(rParticle
.mPosition
, maGenerator
);
101 mrDataProvider
.initializeVariables(rParticle
.mVelocity
, maGenerator
);
103 for (size_t k
= 0; k
< mnDimensionality
; k
++)
105 rParticle
.mPosition
[k
] = mrDataProvider
.clampVariable(k
, rParticle
.mPosition
[k
]);
108 rParticle
.mCurrentFitness
= mrDataProvider
.calculateFitness(rParticle
.mPosition
);
110 for (size_t k
= 0; k
< mnDimensionality
; k
++)
112 rParticle
.mPosition
[k
] = mrDataProvider
.clampVariable(k
, rParticle
.mPosition
[k
]);
115 rParticle
.mBestPosition
.insert(rParticle
.mBestPosition
.begin(),
116 rParticle
.mPosition
.begin(), rParticle
.mPosition
.end());
117 rParticle
.mBestFitness
= rParticle
.mCurrentFitness
;
119 if (rParticle
.mCurrentFitness
> mfBestFitness
)
121 mfBestFitness
= rParticle
.mCurrentFitness
;
122 maBestPosition
.insert(maBestPosition
.begin(), rParticle
.mPosition
.begin(),
123 rParticle
.mPosition
.end());
130 bool bBestChanged
= false;
132 for (Particle
& rParticle
: maSwarm
)
134 double fRandom1
= maRandom01(maGenerator
);
135 double fRandom2
= maRandom01(maGenerator
);
137 for (size_t k
= 0; k
< mnDimensionality
; k
++)
139 rParticle
.mVelocity
[k
]
140 = (constWeight
* rParticle
.mVelocity
[k
])
141 + (c1
* fRandom1
* (rParticle
.mBestPosition
[k
] - rParticle
.mPosition
[k
]))
142 + (c2
* fRandom2
* (maBestPosition
[k
] - rParticle
.mPosition
[k
]));
144 mrDataProvider
.clampVariable(k
, rParticle
.mVelocity
[k
]);
146 rParticle
.mPosition
[k
] += rParticle
.mVelocity
[k
];
147 rParticle
.mPosition
[k
] = mrDataProvider
.clampVariable(k
, rParticle
.mPosition
[k
]);
150 rParticle
.mCurrentFitness
= mrDataProvider
.calculateFitness(rParticle
.mPosition
);
152 if (rParticle
.mCurrentFitness
> rParticle
.mBestFitness
)
154 rParticle
.mBestFitness
= rParticle
.mCurrentFitness
;
155 rParticle
.mBestPosition
.insert(rParticle
.mBestPosition
.begin(),
156 rParticle
.mPosition
.begin(),
157 rParticle
.mPosition
.end());
160 if (rParticle
.mCurrentFitness
> mfBestFitness
)
162 if (std::abs(rParticle
.mCurrentFitness
- mfBestFitness
) > constAcceptedPrecision
)
165 mnLastChange
= mnGeneration
;
167 maBestPosition
.insert(maBestPosition
.begin(), rParticle
.mPosition
.begin(),
168 rParticle
.mPosition
.end());
169 mfBestFitness
= rParticle
.mCurrentFitness
;
177 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */