27 #ifndef SHARK_ALGORITHMS_DIRECTSEARCH_HYPERVOLUMESUBSETSELECTION_2D_H 28 #define SHARK_ALGORITHMS_DIRECTSEARCH_HYPERVOLUMESUBSETSELECTION_2D_H 60 Point(
double f1,
double f2, std::size_t index)
67 bool operator<(Point
const& rhs)
const{
68 if (f1 < rhs.f1)
return true;
69 if (f1 > rhs.f1)
return false;
94 struct LinearFunction{
100 LinearFunction(
double a,
double b, std::size_t index = 0):a(a), b(b), index(index){}
103 double eval(
double x)
const{
109 double Intersection(LinearFunction f1, LinearFunction f2)
const{
110 return (f2.b - f1.b) / (f1.a - f2.a);
119 std::pair<std::vector<double>,std::vector<std::size_t> > upperEnvelope(
120 std::vector<LinearFunction>
const& functions,
121 std::vector<Point>
const& points
124 std::size_t n = points.size();
125 std::vector<double>
h(n);
126 std::vector<std::size_t> chosen(n);
127 std::deque<LinearFunction> s;
144 for (std::size_t i = 0; i != n; ++i) {
152 while (s.size() > 1 ) {
154 double d1 = Intersection(functions[i], s.end()[-1]);
155 double d2 = Intersection(s.end()[-2], s.end()[-1]);
157 if (d1 <= d2 || std::abs(d1-d2) < 1.e-10) {
164 s.push_back(functions[i]);
171 while (s.size() > 1) {
172 double d1 = s[0].eval(points[i].f1);
173 double d2 = s[1].eval(points[i].f1);
175 if (d1 < d2 || std::abs(d1-d2) < 1.e-10) {
184 h[i] = s[0].eval(points[i].f1);
185 chosen[i] = s[0].index;
187 return std::make_pair(std::move(h),std::move(chosen));
193 void hypSSP(std::vector<Point>& front,std::size_t k)
const{
195 SHARK_RUNTIME_CHECK( k <= front.size(),
"The front must have at least k nondominated points");
197 std::size_t n = front.size();
198 std::vector<LinearFunction> functions(n);
200 std::vector<std::vector<std::size_t> > chosen;
201 std::vector<double>
h(n,0.0);
202 for(std::size_t j=0; j != k-1; ++j) {
203 for(std::size_t i=0; i != n; ++i ) {
204 functions[i] = LinearFunction( -front[i].f2, front[i].f1* front[i].f2 + h[i]);
206 auto result = upperEnvelope(functions, front);
208 chosen.push_back(result.second);
212 std::size_t currentIndex = 0;
214 for(std::size_t i=0; i != n; ++i ) {
215 LinearFunction f(-front[i].f2, front[i].f1*front[i].f2 + h[i]);
216 if(f.eval(0) > res) {
221 front[currentIndex].selected =
true;
223 for(
auto pos = chosen.rbegin(); pos != chosen.rend(); ++pos){
224 currentIndex = (*pos)[currentIndex];
225 front[currentIndex].selected =
true;
229 template<
typename Set>
230 std::vector<Point> createFront(Set
const& points,
double refX,
double refY)
const{
232 std::vector<Point> front;
233 for(std::size_t i = 0; i != points.size(); ++i){
234 front.emplace_back(points[i](0) - refX, points[i](1) - refY,i);
236 std::sort(front.begin(),front.end());
238 auto newEnd = std::unique(front.begin(),front.end(),[](Point
const& x, Point
const& y){
241 front.erase(newEnd,front.end());
255 template<
typename Set,
typename SelectedSet,
typename VectorType >
263 for(
auto&& s: selected)
266 std::vector<Point> front = createFront(points, refPoint(0), refPoint(1));
271 for(Point
const& point: front){
273 selected[point.index] =
true;
289 template<
typename Set,
typename SelectedSet>
290 void operator()( Set
const& points, SelectedSet& selected, std::size_t k){
297 for(
auto&& s: selected)
301 std::vector<Point> front = createFront(points, 0,0);
304 double refX= front.back().f1;
305 double refY= front.front().f2;
307 for(
auto&& point: front){
313 selected[front.front().index] =
true;
314 selected[front.back().index] =
true;
316 front.erase(front.begin(),front.begin()+1);
322 for(Point
const& point: front){
324 selected[point.index] =
true;