SteadyStateMOCMA.h
Go to the documentation of this file.
1/*!
2 *
3 *
4 * \brief SteadyStateMOCMA.h
5 *
6 * \author T.Voss
7 * \date 2010
8 *
9 *
10 * \par Copyright 1995-2017 Shark Development Team
11 *
12 * <BR><HR>
13 * This file is part of Shark.
14 * <http://shark-ml.org/>
15 *
16 * Shark is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU Lesser General Public License as published
18 * by the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * Shark is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU Lesser General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public License
27 * along with Shark. If not, see <http://www.gnu.org/licenses/>.
28 *
29 */
30#ifndef SHARK_ALGORITHMS_DIRECT_SEARCH_STEADYSTATEMOCMA
31#define SHARK_ALGORITHMS_DIRECT_SEARCH_STEADYSTATEMOCMA
32
33// MOO specific stuff
39
41
42namespace shark {
43
44/// \brief Implements the \f$(\mu+1)\f$-MO-CMA-ES.
45///
46/// Please see the following papers for further reference:
47/// - Igel, Suttorp and Hansen. Steady-state Selection and Efficient Covariance Matrix Update in the Multi-Objective CMA-ES.
48/// - Voß, Hansen and Igel. Improved Step Size Adaptation for the MO-CMA-ES.
49/// \ingroup multidirect
50template<typename Indicator=HypervolumeIndicator>
52public:
57public:
58
59 IndicatorBasedSteadyStateMOCMA(random::rng_type& rng = random::globalRng):mpe_rng(&rng){
60 m_individualSuccessThreshold = 0.44;
61 initialSigma() = 1.0;
62 mu() = 100;
65 }
66
67 /**
68 * \brief Returns the name of the algorithm.
69 */
70 std::string name() const {
71 return "SteadyStateMOCMA";
72 }
73
74 std::size_t mu()const{
75 return m_mu;
76 }
77 std::size_t& mu(){
78 return m_mu;
79 }
80
81 std::size_t numInitPoints() const{
82 return m_mu;
83 }
84
85 double initialSigma()const{
86 return m_initialSigma;
87 }
88 double& initialSigma(){
89 return m_initialSigma;
90 }
91
93 return m_notionOfSuccess;
94 }
96 return m_notionOfSuccess;
97 }
98
99 Indicator& indicator(){
100 return m_selection.indicator();
101 }
102 Indicator const& indicator()const{
103 return m_selection.indicator();
104 }
105
106 void read( InArchive & archive ){
107 archive >> BOOST_SERIALIZATION_NVP(m_parents);
108 archive >> BOOST_SERIALIZATION_NVP(m_mu);
109 archive >> BOOST_SERIALIZATION_NVP(m_best);
110
111 archive >> BOOST_SERIALIZATION_NVP(m_selection);
112 archive >> BOOST_SERIALIZATION_NVP(m_notionOfSuccess);
113 archive >> BOOST_SERIALIZATION_NVP(m_individualSuccessThreshold);
114 archive >> BOOST_SERIALIZATION_NVP(m_initialSigma);
115 }
116 void write( OutArchive & archive ) const{
117 archive << BOOST_SERIALIZATION_NVP(m_parents);
118 archive << BOOST_SERIALIZATION_NVP(m_mu);
119 archive << BOOST_SERIALIZATION_NVP(m_best);
120
121 archive << BOOST_SERIALIZATION_NVP(m_selection);
122 archive << BOOST_SERIALIZATION_NVP(m_notionOfSuccess);
123 archive << BOOST_SERIALIZATION_NVP(m_individualSuccessThreshold);
124 archive << BOOST_SERIALIZATION_NVP(m_initialSigma);
125 }
126
127 using AbstractMultiObjectiveOptimizer<RealVector >::init;
128 /**
129 * \brief Initializes the algorithm for the supplied objective function.
130 *
131 * \param [in] function The objective function.
132 * \param [in] initialSearchPoints A set of intiial search points.
133 */
134 void init(
135 ObjectiveFunctionType const& function,
136 std::vector<SearchPointType> const& initialSearchPoints
137 ){
138 checkFeatures(function);
139 std::vector<RealVector> values(initialSearchPoints.size());
140 for(std::size_t i = 0; i != initialSearchPoints.size(); ++i){
141 SHARK_RUNTIME_CHECK(function.isFeasible(initialSearchPoints[i]),"Starting point(s) not feasible");
142 values[i] = function.eval(initialSearchPoints[i]);
143 }
144 this->doInit(initialSearchPoints,values,mu(),initialSigma() );
145 }
146
147 /**
148 * \brief Executes one iteration of the algorithm.
149 *
150 * \param [in] function The function to iterate upon.
151 */
152 void step( ObjectiveFunctionType const& function ) {
153 std::vector<IndividualType> offspring = generateOffspring();
154 PenalizingEvaluator penalizingEvaluator;
155 penalizingEvaluator( function, offspring.begin(), offspring.end() );
156 updatePopulation(offspring);
157 }
158protected:
159 /// \brief The individual type of the SteadyState-MOCMA.
161
162 void doInit(
163 std::vector<SearchPointType> const& initialSearchPoints,
164 std::vector<ResultType> const& functionValues,
165 std::size_t mu,
166 double initialSigma
167 ){
168 SIZE_CHECK(initialSearchPoints.size() > 0);
169
170 m_mu = mu;
171 m_initialSigma = initialSigma;
172
173 m_best.resize( mu );
174 m_parents.resize( mu );
175 std::size_t noVariables = initialSearchPoints[0].size();
176
177 //if the number of supplied points is smaller than mu, fill everything in
178 std::size_t numPoints = 0;
179 if(initialSearchPoints.size()<=mu){
180 numPoints = initialSearchPoints.size();
181 for(std::size_t i = 0; i != numPoints; ++i){
182 m_parents[i] = IndividualType(noVariables,m_individualSuccessThreshold,m_initialSigma);
183 m_parents[i].searchPoint() = initialSearchPoints[i];
184 m_parents[i].penalizedFitness() = functionValues[i];
185 m_parents[i].unpenalizedFitness() = functionValues[i];
186 }
187 }
188 //copy points randomly
189 for(std::size_t i = numPoints; i != mu; ++i){
190 std::size_t index = random::discrete(*mpe_rng, std::size_t(0),initialSearchPoints.size()-1);
191 m_parents[i] = IndividualType(noVariables,m_individualSuccessThreshold,m_initialSigma);
192 m_parents[i].searchPoint() = initialSearchPoints[index];
193 m_parents[i].penalizedFitness() = functionValues[index];
194 m_parents[i].unpenalizedFitness() = functionValues[index];
195 }
196 //create initial mu best points
197 for(std::size_t i = 0; i != mu; ++i){
198 m_best[i].point = m_parents[i].searchPoint();
199 m_best[i].value = m_parents[i].unpenalizedFitness();
200 }
201 indicator().init(functionValues.front().size(),mu,*mpe_rng);
202 m_selection(m_parents,mu);
203 sortRankOneToFront();
204 }
205
206 std::vector<IndividualType> generateOffspring()const{
207 //find the last element with rank 1
208 std::size_t maxIdx = 0;
209 for (; maxIdx < m_parents.size(); maxIdx++) {
210 if (m_parents[maxIdx].rank() != 1)
211 break;
212 }
213 //sample a random parent with rank 1
214 std::size_t parentId = random::discrete(*mpe_rng, std::size_t(0), maxIdx-1);
215 std::vector<IndividualType> offspring;
216 offspring.push_back(m_parents[parentId]);
217 offspring[0].mutate(*mpe_rng);
218 offspring[0].parent() = parentId;
219 return offspring;
220 }
221
222 void updatePopulation( std::vector<IndividualType> const& offspringVec) {
223 m_parents.push_back(offspringVec[0]);
224 m_selection( m_parents, mu());
225
226 IndividualType& offspring = m_parents.back();
227 IndividualType& parent = m_parents[offspring.parent()];
228
229 if (m_notionOfSuccess == IndividualBased && offspring.selected()) {
230 offspring.updateAsOffspring();
232 }
233 else if (m_notionOfSuccess == PopulationBased && offspring.selected() && offspring.rank() <= parent.rank() ) {
234 offspring.updateAsOffspring();
236 }else{
238 }
239
240 //if the individual got selected, insert it into the parent population
241 if(m_parents.back().selected()){
242 for(std::size_t i = 0; i != mu(); ++i){
243 if(!m_parents[i].selected()){
244 m_best[i].point = m_parents.back().searchPoint();
245 m_best[i].value = m_parents.back().unpenalizedFitness();
246 m_parents[i] = m_parents.back();
247 break;
248 }
249 }
250 }
251 m_parents.pop_back();
252 sortRankOneToFront();
253 }
254
255 std::vector<IndividualType> m_parents; ///< Population of size \f$\mu + 1\f$.
256private:
257 std::size_t m_mu; ///< Size of parent population
258
259 IndicatorBasedSelection<Indicator> m_selection; ///< Selection operator relying on the (contributing) hypervolume indicator.
260
261 NotionOfSuccess m_notionOfSuccess; ///< Flag for deciding whether the improved step-size adaptation shall be used.
262 double m_individualSuccessThreshold;
263 double m_initialSigma;
264
265 /// \brief sorts all individuals with rank one to the front
266 void sortRankOneToFront(){
267 std::size_t start = 0;
268 std::size_t end = mu()-1;
269 while(start != end){
270 if(m_parents[start].rank() == 1){
271 ++start;
272 }else if(m_parents[end].rank() != 1){
273 --end;
274 }else{
275 swap(m_parents[start],m_parents[end]);
276 swap(m_best[start],m_best[end]);
277 }
278 }
279 }
280
281 random::rng_type* mpe_rng;
282};
283
286
287}
288
289#endif