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 
42 namespace shark {
43 
44 /**
45  * \brief Implements the \f$(\mu+1)\f$-MO-CMA-ES.
46  *
47  * Please see the following papers for further reference:
48  * - Igel, Suttorp and Hansen. Steady-state Selection and Efficient Covariance Matrix Update in the Multi-Objective CMA-ES.
49  * - Voß, Hansen and Igel. Improved Step Size Adaptation for the MO-CMA-ES.
50  */
51 template<typename Indicator=HypervolumeIndicator>
53 public:
57  };
58 public:
59 
60  IndicatorBasedSteadyStateMOCMA(random::rng_type& rng = random::globalRng):mpe_rng(&rng){
61  m_individualSuccessThreshold = 0.44;
62  initialSigma() = 1.0;
63  mu() = 100;
66  }
67 
68  /**
69  * \brief Returns the name of the algorithm.
70  */
71  std::string name() const {
72  return "SteadyStateMOCMA";
73  }
74 
75  std::size_t mu()const{
76  return m_mu;
77  }
78  std::size_t& mu(){
79  return m_mu;
80  }
81 
82  std::size_t numInitPoints() const{
83  return m_mu;
84  }
85 
86  double initialSigma()const{
87  return m_initialSigma;
88  }
89  double& initialSigma(){
90  return m_initialSigma;
91  }
92 
94  return m_notionOfSuccess;
95  }
97  return m_notionOfSuccess;
98  }
99 
100  Indicator& indicator(){
101  return m_selection.indicator();
102  }
103  Indicator const& indicator()const{
104  return m_selection.indicator();
105  }
106 
107  void read( InArchive & archive ){
108  archive >> BOOST_SERIALIZATION_NVP(m_parents);
109  archive >> BOOST_SERIALIZATION_NVP(m_mu);
110  archive >> BOOST_SERIALIZATION_NVP(m_best);
111 
112  archive >> BOOST_SERIALIZATION_NVP(m_selection);
113  archive >> BOOST_SERIALIZATION_NVP(m_notionOfSuccess);
114  archive >> BOOST_SERIALIZATION_NVP(m_individualSuccessThreshold);
115  archive >> BOOST_SERIALIZATION_NVP(m_initialSigma);
116  }
117  void write( OutArchive & archive ) const{
118  archive << BOOST_SERIALIZATION_NVP(m_parents);
119  archive << BOOST_SERIALIZATION_NVP(m_mu);
120  archive << BOOST_SERIALIZATION_NVP(m_best);
121 
122  archive << BOOST_SERIALIZATION_NVP(m_selection);
123  archive << BOOST_SERIALIZATION_NVP(m_notionOfSuccess);
124  archive << BOOST_SERIALIZATION_NVP(m_individualSuccessThreshold);
125  archive << BOOST_SERIALIZATION_NVP(m_initialSigma);
126  }
127 
129  /**
130  * \brief Initializes the algorithm for the supplied objective function.
131  *
132  * \param [in] function The objective function.
133  * \param [in] initialSearchPoints A set of intiial search points.
134  */
135  void init(
136  ObjectiveFunctionType const& function,
137  std::vector<SearchPointType> const& initialSearchPoints
138  ){
139  checkFeatures(function);
140  std::vector<RealVector> values(initialSearchPoints.size());
141  for(std::size_t i = 0; i != initialSearchPoints.size(); ++i){
142  SHARK_RUNTIME_CHECK(function.isFeasible(initialSearchPoints[i]),"Starting point(s) not feasible");
143  values[i] = function.eval(initialSearchPoints[i]);
144  }
145  this->doInit(initialSearchPoints,values,mu(),initialSigma() );
146  }
147 
148  /**
149  * \brief Executes one iteration of the algorithm.
150  *
151  * \param [in] function The function to iterate upon.
152  */
153  void step( ObjectiveFunctionType const& function ) {
154  std::vector<IndividualType> offspring = generateOffspring();
155  PenalizingEvaluator penalizingEvaluator;
156  penalizingEvaluator( function, offspring.begin(), offspring.end() );
157  updatePopulation(offspring);
158  }
159 protected:
160  /// \brief The individual type of the SteadyState-MOCMA.
162 
163  void doInit(
164  std::vector<SearchPointType> const& initialSearchPoints,
165  std::vector<ResultType> const& functionValues,
166  std::size_t mu,
167  double initialSigma
168  ){
169  SIZE_CHECK(initialSearchPoints.size() > 0);
170 
171  m_mu = mu;
172  m_initialSigma = initialSigma;
173 
174  m_best.resize( mu );
175  m_parents.resize( mu );
176  std::size_t noVariables = initialSearchPoints[0].size();
177 
178  //if the number of supplied points is smaller than mu, fill everything in
179  std::size_t numPoints = 0;
180  if(initialSearchPoints.size()<=mu){
181  numPoints = initialSearchPoints.size();
182  for(std::size_t i = 0; i != numPoints; ++i){
183  m_parents[i] = IndividualType(noVariables,m_individualSuccessThreshold,m_initialSigma);
184  m_parents[i].searchPoint() = initialSearchPoints[i];
185  m_parents[i].penalizedFitness() = functionValues[i];
186  m_parents[i].unpenalizedFitness() = functionValues[i];
187  }
188  }
189  //copy points randomly
190  for(std::size_t i = numPoints; i != mu; ++i){
191  std::size_t index = random::discrete(*mpe_rng, std::size_t(0),initialSearchPoints.size()-1);
192  m_parents[i] = IndividualType(noVariables,m_individualSuccessThreshold,m_initialSigma);
193  m_parents[i].searchPoint() = initialSearchPoints[index];
194  m_parents[i].penalizedFitness() = functionValues[index];
195  m_parents[i].unpenalizedFitness() = functionValues[index];
196  }
197  //create initial mu best points
198  for(std::size_t i = 0; i != mu; ++i){
199  m_best[i].point = m_parents[i].searchPoint();
200  m_best[i].value = m_parents[i].unpenalizedFitness();
201  }
202  indicator().init(functionValues.front().size(),mu,*mpe_rng);
203  m_selection(m_parents,mu);
204  sortRankOneToFront();
205  }
206 
207  std::vector<IndividualType> generateOffspring()const{
208  //find the last element with rank 1
209  std::size_t maxIdx = 0;
210  for (; maxIdx < m_parents.size(); maxIdx++) {
211  if (m_parents[maxIdx].rank() != 1)
212  break;
213  }
214  //sample a random parent with rank 1
215  std::size_t parentId = random::discrete(*mpe_rng, std::size_t(0), maxIdx-1);
216  std::vector<IndividualType> offspring;
217  offspring.push_back(m_parents[parentId]);
218  offspring[0].mutate(*mpe_rng);
219  offspring[0].parent() = parentId;
220  return offspring;
221  }
222 
223  void updatePopulation( std::vector<IndividualType> const& offspringVec) {
224  m_parents.push_back(offspringVec[0]);
225  m_selection( m_parents, mu());
226 
227  IndividualType& offspring = m_parents.back();
228  IndividualType& parent = m_parents[offspring.parent()];
229 
230  if (m_notionOfSuccess == IndividualBased && offspring.selected()) {
231  offspring.updateAsOffspring();
233  }
234  else if (m_notionOfSuccess == PopulationBased && offspring.selected() && offspring.rank() <= parent.rank() ) {
235  offspring.updateAsOffspring();
237  }else{
239  }
240 
241  //if the individual got selected, insert it into the parent population
242  if(m_parents.back().selected()){
243  for(std::size_t i = 0; i != mu(); ++i){
244  if(!m_parents[i].selected()){
245  m_best[i].point = m_parents.back().searchPoint();
246  m_best[i].value = m_parents.back().unpenalizedFitness();
247  m_parents[i] = m_parents.back();
248  break;
249  }
250  }
251  }
252  m_parents.pop_back();
253  sortRankOneToFront();
254  }
255 
256  std::vector<IndividualType> m_parents; ///< Population of size \f$\mu + 1\f$.
257 private:
258  std::size_t m_mu; ///< Size of parent population
259 
260  IndicatorBasedSelection<Indicator> m_selection; ///< Selection operator relying on the (contributing) hypervolume indicator.
261 
262  NotionOfSuccess m_notionOfSuccess; ///< Flag for deciding whether the improved step-size adaptation shall be used.
263  double m_individualSuccessThreshold;
264  double m_initialSigma;
265 
266  /// \brief sorts all individuals with rank one to the front
267  void sortRankOneToFront(){
268  std::size_t start = 0;
269  std::size_t end = mu()-1;
270  while(start != end){
271  if(m_parents[start].rank() == 1){
272  ++start;
273  }else if(m_parents[end].rank() != 1){
274  --end;
275  }else{
276  swap(m_parents[start],m_parents[end]);
277  swap(m_best[start],m_best[end]);
278  }
279  }
280  }
281 
282  random::rng_type* mpe_rng;
283 };
284 
287 
288 }
289 
290 #endif