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/.
11 #ifndef INCLUDED_SCCOMP_SOURCE_PARTICLESWARM_HXX
12 #define INCLUDED_SCCOMP_SOURCE_PARTICLESWARM_HXX
20 Particle(size_t nDimensionality
)
21 : mVelocity(nDimensionality
)
22 , mPosition(nDimensionality
)
23 , mCurrentFitness(std::numeric_limits
<float>::lowest())
24 , mBestPosition(nDimensionality
)
25 , mBestFitness(std::numeric_limits
<float>::lowest())
29 std::vector
<double> mVelocity
;
31 std::vector
<double> mPosition
;
32 double mCurrentFitness
;
34 std::vector
<double> mBestPosition
;
38 template <typename DataProvider
> class ParticleSwarmOptimizationAlgorithm
42 static constexpr double constWeight
= 0.729;
43 // cognitive coefficient
44 static constexpr double c1
= 1.49445;
46 static constexpr double c2
= 1.49445;
48 static constexpr double constAcceptedPrecision
= 0.000000001;
50 DataProvider
& mrDataProvider
;
52 size_t const mnNumOfParticles
;
54 std::vector
<Particle
> maSwarm
;
56 std::random_device maRandomDevice
;
57 std::mt19937 maGenerator
;
58 size_t mnDimensionality
;
60 std::uniform_real_distribution
<> maRandom01
;
62 std::vector
<double> maBestPosition
;
68 ParticleSwarmOptimizationAlgorithm(DataProvider
& rDataProvider
, size_t nNumOfParticles
)
69 : mrDataProvider(rDataProvider
)
70 , mnNumOfParticles(nNumOfParticles
)
71 , maGenerator(maRandomDevice())
72 , mnDimensionality(mrDataProvider
.getDimensionality())
73 , maRandom01(0.0, 1.0)
74 , maBestPosition(mnDimensionality
)
75 , mfBestFitness(std::numeric_limits
<float>::lowest())
81 std::vector
<double> const& getResult() { return maBestPosition
; }
83 int getGeneration() { return mnGeneration
; }
85 int getLastChange() { return mnLastChange
; }
93 mfBestFitness
= std::numeric_limits
<float>::lowest();
95 maSwarm
.reserve(mnNumOfParticles
);
96 for (size_t i
= 0; i
< mnNumOfParticles
; i
++)
98 maSwarm
.emplace_back(mnDimensionality
);
99 Particle
& rParticle
= maSwarm
.back();
101 mrDataProvider
.initializeVariables(rParticle
.mPosition
, maGenerator
);
102 mrDataProvider
.initializeVariables(rParticle
.mVelocity
, maGenerator
);
104 for (size_t k
= 0; k
< mnDimensionality
; k
++)
106 rParticle
.mPosition
[k
] = mrDataProvider
.clampVariable(k
, rParticle
.mPosition
[k
]);
109 rParticle
.mCurrentFitness
= mrDataProvider
.calculateFitness(rParticle
.mPosition
);
111 for (size_t k
= 0; k
< mnDimensionality
; k
++)
113 rParticle
.mPosition
[k
] = mrDataProvider
.clampVariable(k
, rParticle
.mPosition
[k
]);
116 std::copy(rParticle
.mPosition
.begin(), rParticle
.mPosition
.end(),
117 rParticle
.mBestPosition
.begin());
118 rParticle
.mBestFitness
= rParticle
.mCurrentFitness
;
120 if (rParticle
.mCurrentFitness
> mfBestFitness
)
122 mfBestFitness
= rParticle
.mCurrentFitness
;
123 std::copy(rParticle
.mPosition
.begin(), rParticle
.mPosition
.end(),
124 maBestPosition
.begin());
131 bool bBestChanged
= false;
133 for (Particle
& rParticle
: maSwarm
)
135 double fRandom1
= maRandom01(maGenerator
);
136 double fRandom2
= maRandom01(maGenerator
);
138 for (size_t k
= 0; k
< mnDimensionality
; k
++)
140 rParticle
.mVelocity
[k
]
141 = (constWeight
* rParticle
.mVelocity
[k
])
142 + (c1
* fRandom1
* (rParticle
.mBestPosition
[k
] - rParticle
.mPosition
[k
]))
143 + (c2
* fRandom2
* (maBestPosition
[k
] - rParticle
.mPosition
[k
]));
145 mrDataProvider
.clampVariable(k
, rParticle
.mVelocity
[k
]);
147 rParticle
.mPosition
[k
] += rParticle
.mVelocity
[k
];
148 rParticle
.mPosition
[k
] = mrDataProvider
.clampVariable(k
, rParticle
.mPosition
[k
]);
151 rParticle
.mCurrentFitness
= mrDataProvider
.calculateFitness(rParticle
.mPosition
);
153 if (rParticle
.mCurrentFitness
> rParticle
.mBestFitness
)
155 rParticle
.mBestFitness
= rParticle
.mCurrentFitness
;
156 std::copy(rParticle
.mPosition
.begin(), rParticle
.mPosition
.end(),
157 rParticle
.mBestPosition
.begin());
160 if (rParticle
.mCurrentFitness
> mfBestFitness
)
162 if (std::abs(rParticle
.mCurrentFitness
- mfBestFitness
) > constAcceptedPrecision
)
165 mnLastChange
= mnGeneration
;
167 std::copy(rParticle
.mPosition
.begin(), rParticle
.mPosition
.end(),
168 maBestPosition
.begin());
169 mfBestFitness
= rParticle
.mCurrentFitness
;
179 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */