HypervolumeContributionMD.h
Go to the documentation of this file.
1/*!
2 *
3 * \author O.Krause, T. Glasmachers
4 * \date 2014-2016
5 *
6 *
7 * \par Copyright 1995-2017 Shark Development Team
8 *
9 * <BR><HR>
10 * This file is part of Shark.
11 * <https://shark-ml.github.io/Shark/>
12 *
13 * Shark is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as published
15 * by the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * Shark is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with Shark. If not, see <http://www.gnu.org/licenses/>.
25 *
26 */
27#ifndef SHARK_ALGORITHMS_DIRECTSEARCH_HYPERVOLUME_CONTRIBUTION_MD_H
28#define SHARK_ALGORITHMS_DIRECTSEARCH_HYPERVOLUME_CONTRIBUTION_MD_H
29
30#include <shark/LinAlg/Base.h>
32#include <shark/Core/OpenMP.h>
35
36#include <algorithm>
37#include <vector>
38
39namespace shark {
40/// \brief Finds the hypervolume contribution for points in MD
41///
42/// This implementation is slightly less naive. Instead of calculating Hyp{S}-Hyp{S/x}
43/// directly, we restrict the volume dominated by points in S to be inside the box [x,ref]. This
44/// leads to points in S not being relevant for the computation and thus can be discarded using
45/// a simple dominance test.
47 /// \brief Returns the index of the points with smallest contribution.
48 ///
49 /// \param [in] points The set \f$S\f$ of points from which to select the smallest contributor.
50 /// \param [in] k The number of points to select.
51 /// \param [in] ref The reference Point\f$\vec{r} \in \mathbb{R}^2\f$ for the hypervolume calculation, needs to fulfill: \f$ \forall s \in S: s \preceq \vec{r}\f$.
52 template<class Set, typename VectorType>
53 std::vector<KeyValuePair<double,std::size_t> > smallest(Set const& points, std::size_t k, VectorType const& ref)const{
54 SHARK_RUNTIME_CHECK(points.size() >= k, "There must be at least k points in the set");
56 std::vector<KeyValuePair<double,std::size_t> > result( points.size() );
57 SHARK_PARALLEL_FOR( int i = 0; i < static_cast< int >( points.size() ); i++ ) {
58 auto const& point = points[i];
59
60 //compute restricted pointset
61 std::vector<RealVector> pointset( points.begin(), points.end() );
62 pointset.erase( pointset.begin() + i );
63 restrictSet(pointset,point);
64
65 double baseVol = std::exp(sum(log(ref-point)));
66 result[i].key = baseVol - hv(pointset,ref);
67 result[i].value = i;
68 }
69 std::sort(result.begin(),result.end());
70 result.erase(result.begin()+k,result.end());
71
72 return result;
73 }
74
75 /// \brief Returns the index of the points with largest contribution.
76 ///
77 /// \param [in] points The set \f$S\f$ of points from which to select the smallest contributor.
78 /// \param [in] k Number of points.
79 /// \param [in] ref The reference Point\f$\vec{r} \in \mathbb{R}^2\f$ for the hypervolume calculation, needs to fulfill: \f$ \forall s \in S: s \preceq \vec{r}\f$.
80 template<class Set, typename VectorType>
81 std::vector<KeyValuePair<double,std::size_t> > largest(Set const& points, std::size_t k, VectorType const& ref)const{
82 SHARK_RUNTIME_CHECK(points.size() >= k, "There must be at least k points in the set");
84 std::vector<KeyValuePair<double,std::size_t> > result( points.size() );
85 SHARK_PARALLEL_FOR( int i = 0; i < static_cast< int >( points.size() ); i++ ) {
86 auto const& point = points[i];
87
88 //compute restricted pointset
89 std::vector<RealVector> pointset( points.begin(), points.end() );
90 pointset.erase( pointset.begin() + i );
91 restrictSet(pointset,point);
92
93 double baseVol = std::exp(sum(log(ref-point)));
94 result[i].key = baseVol - hv(pointset,ref);
95 result[i].value = i;
96 }
97 std::sort(result.begin(),result.end());
98 result.erase(result.begin(),result.end()-k);
99 std::reverse(result.begin(),result.end());
100 return result;
101 }
102
103 /// \brief Returns the index of the points with smallest contribution.
104 ///
105 /// As no reference point is given, the extremum points can not be computed and are never selected.
106 ///
107 /// \param [in] points The set \f$S\f$ of points from which to select the smallest contributor.
108 /// \param [in] k The number of points to select.
109 template<class Set>
110 std::vector<KeyValuePair<double,std::size_t> > smallest(Set const& points, std::size_t k)const{
111 SHARK_RUNTIME_CHECK(points.size() >= k, "There must be at least k points in the set");
112 //find reference point as well as points with lowest function value
113 std::vector<std::size_t> minIndex(points[0].size(),0);
114 RealVector minVal = points[0];
115 RealVector ref=points[0];
116 for(std::size_t i = 1; i != points.size(); ++i){
117 noalias(ref) = max(ref,points[i]);
118 for(std::size_t j = 0; j != minVal.size(); ++j){
119 if(points[i](j)< minVal[j]){
120 minVal[j] = points[i](j);
121 minIndex[j]=i;
122 }
123 }
124 }
126 std::vector<KeyValuePair<double,std::size_t> > result;
127 SHARK_PARALLEL_FOR( int i = 0; i < static_cast< int >( points.size() ); i++ ) {
128 if(std::find(minIndex.begin(),minIndex.end(),i) != minIndex.end())
129 continue;
130
131 auto const& point = points[i];
132
133 //compute restricted pointset
134 std::vector<RealVector> pointset( points.begin(), points.end() );
135 pointset.erase( pointset.begin() + i );
136 restrictSet(pointset,point);
137
138 double baseVol = std::exp(sum(log(ref-point)));
139 double volume = baseVol - hv(pointset,ref);
141 result.emplace_back(volume,i);
142 }
143 }
144 std::sort(result.begin(),result.end());
145 result.erase(result.begin()+k,result.end());
146
147 return result;
148 }
149
150 /// \brief Returns the index of the points with largest contribution.
151 ///
152 /// As no reference point is given, the extremum points can not be computed and are never selected.
153 ///
154 /// \param [in] points The set \f$S\f$ of points from which to select the smallest contributor.
155 /// \param [in] k The number of points to select.
156 template<class Set>
157 std::vector<KeyValuePair<double,std::size_t> > largest(Set const& points, std::size_t k)const{
158 SHARK_RUNTIME_CHECK(points.size() >= k, "There must be at least k points in the set");
159 //find reference point as well as points with lowest function value
160 std::vector<std::size_t> minIndex(points[0].size(),0);
161 RealVector minVal = points[0];
162 RealVector ref=points[0];
163 for(std::size_t i = 1; i != points.size(); ++i){
164 noalias(ref) = max(ref,points[i]);
165 for(std::size_t j = 0; j != minVal.size(); ++j){
166 if(points[i](j)< minVal[j]){
167 minVal[j] = points[i](j);
168 minIndex[j]=i;
169 }
170 }
171 }
172
174 std::vector<KeyValuePair<double,std::size_t> > result;
175 SHARK_PARALLEL_FOR( int i = 0; i < static_cast< int >( points.size() ); i++ ) {
176 if(std::find(minIndex.begin(),minIndex.end(),i) != minIndex.end())
177 continue;
178 auto const& point = points[i];
179
180 //compute restricted pointset
181 std::vector<RealVector> pointset( points.begin(), points.end() );
182 pointset.erase( pointset.begin() + i );
183 restrictSet(pointset,point);
184
185 double baseVol = std::exp(sum(log(ref-point)));
186 double volume = baseVol - hv(pointset,ref);
188 result.emplace_back(volume,i);
189 }
190 }
191 std::sort(result.begin(),result.end());
192 result.erase(result.begin(),result.end()-k);
193 std::reverse(result.begin(),result.end());
194 return result;
195 }
196private:
197 /// \brief Restrict the points to the area covered by point and remove all points which are then dominated
198 template<class Pointset, class Point>
199 void restrictSet(Pointset& pointset, Point const& point) const{
200 for(auto& p: pointset){
201 noalias(p) = max(p,point);
202 }
203 std::vector<std::size_t> ranks(pointset.size());
204 nonDominatedSort(pointset,ranks);
205 std::size_t end = pointset.size();
206 std::size_t pos = 0;
207 while(pos != end){
208 if(ranks[pos] == 1){
209 ++pos;
210 continue;
211 }
212 --end;
213 if(pos != end){
214 std::swap(pointset[pos],pointset[end]);
215 std::swap(ranks[pos],ranks[end]);
216 }
217 }
218 pointset.erase(pointset.begin() +end, pointset.end());
219 }
220};
221
222}
223#endif