//Generate a random weights vector whose sum of all elements is equal to 1 void generate_weights(fitness_vector & weights) { rng_double drng = rng_generator::get<rng_double>(); //generate n random numbers between 0 and 1 and store in weights where n = weights.size() std::generate(weights.begin(), weights.end(), std::bind(fRand, drng)); //caculate the sum of all elements of weights vector double sum = std::accumulate(weights.begin(), weights.end(), 0.0); //divide each element of weights vector by the calculated sum to make the sum of all elements equal to 1 std::transform(weights.begin(), weights.end(), weights.begin(), std::bind1st(std::multiplies<double>(),1/sum)); }
/** * This method should be used both as a solution to 3D cases, and as a general termination method for algorithms that reduce D-dimensional problem to 3-dimensional one. * * This is the implementation of the algorithm for computing hypervolume as it was presented by Nicola Beume et al. * The implementation uses std::multiset (which is based on red-black tree data structure) as a container for the sweeping front. * Original implementation by Beume et. al uses AVL-tree. * The difference is insiginificant as the important characteristics (maintaining order when traversing, self-balancing) of both structures and the asymptotic times (O(log n) updates) are guaranteed. * Computational complexity: O(n*log(n)) * * @param[in] points vector of points containing the 3-dimensional points for which we compute the hypervolume * @param[in] r_point reference point for the points * * @return hypervolume. */ double hv3d::compute(std::vector<fitness_vector> &points, const fitness_vector &r_point) const { if (m_initial_sorting) { sort(points.begin(), points.end(), fitness_vector_cmp(2,'<')); } double V = 0.0; // hypervolume double A = 0.0; // area of the sweeping plane std::multiset<fitness_vector, fitness_vector_cmp> T(fitness_vector_cmp(0, '>')); // sentinel points (r_point[0], -INF, r_point[2]) and (-INF, r_point[1], r_point[2]) const double INF = std::numeric_limits<double>::max(); fitness_vector sA(r_point.begin(), r_point.end()); sA[1] = -INF; fitness_vector sB(r_point.begin(), r_point.end()); sB[0] = -INF; T.insert(sA); T.insert(sB); double z3 = points[0][2]; T.insert(points[0]); A = fabs((points[0][0] - r_point[0]) * (points[0][1] - r_point[1])); std::multiset<fitness_vector>::iterator p; std::multiset<fitness_vector>::iterator q; for(std::vector<fitness_vector>::size_type idx = 1 ; idx < points.size() ; ++idx) { p = T.insert(points[idx]); q = (p); ++q; //setup q to be a successor of p if ( (*q)[1] <= (*p)[1] ) { // current point is dominated T.erase(p); // disregard the point from further calculation } else { V += A * fabs(z3 - (*p)[2]); z3 = (*p)[2]; std::multiset<fitness_vector>::reverse_iterator rev_it(q); ++rev_it; std::multiset<fitness_vector>::reverse_iterator erase_begin (rev_it); std::multiset<fitness_vector>::reverse_iterator rev_it_pred; while((*rev_it)[1] >= (*p)[1] ) { rev_it_pred = rev_it; ++rev_it_pred; A -= fabs(((*rev_it)[0] - (*rev_it_pred)[0])*((*rev_it)[1] - (*q)[1])); ++rev_it; } A += fabs(((*p)[0] - (*(rev_it))[0])*((*p)[1] - (*q)[1])); T.erase(rev_it.base(),erase_begin.base()); } } V += A * fabs(z3 - r_point[2]); return V; }