30 #include <boost/bind.hpp>
32 namespace pagmo {
namespace util {
namespace hv_algorithm {
38 bool wfg::cmp_points(
double* a,
double* b)
const
40 for(
int i = m_current_slice - 1; i >= 0 ; --i){
43 }
else if(a[i] < b[i]) {
51 wfg::wfg(
const unsigned int stop_dimension) : m_current_slice(0), m_stop_dimension(stop_dimension)
53 if (stop_dimension < 2 ) {
54 pagmo_throw(value_error,
"Stop dimension for WFG must be greater than or equal to 2");
69 allocate_wfg_members(points, r_point);
70 double hv = compute_hv(1);
90 std::vector<double> c;
91 c.reserve(points.size());
94 allocate_wfg_members(points, r_point);
97 double** fr =
new double*[m_max_points];
98 for(
unsigned int i = 0 ; i < m_max_points ; ++i) {
99 fr[i]=
new double[m_current_slice];
101 m_frames[m_n_frames] = fr;
102 m_frames_size[m_n_frames] = 0;
105 for(
unsigned int p_idx = 0 ; p_idx < m_max_points ; ++p_idx) {
106 limitset(0, p_idx, 1);
107 c.push_back(exclusive_hv(p_idx, 1));
117 void wfg::allocate_wfg_members(std::vector<fitness_vector> &points,
const fitness_vector &r_point)
const
119 m_max_points = points.size();
120 m_max_dim = r_point.size();
122 m_refpoint =
new double[m_max_dim];
123 for(
unsigned int d_idx = 0 ; d_idx < m_max_dim ; ++d_idx) {
124 m_refpoint[d_idx] = r_point[d_idx];
129 m_frames =
new double**[m_max_dim];
130 m_frames_size =
new unsigned int[m_max_dim];
133 double** fr =
new double*[m_max_points];
134 for(
unsigned int p_idx = 0 ; p_idx < m_max_points ; ++p_idx) {
135 fr[p_idx] =
new double[m_max_dim];
136 for(
unsigned int d_idx = 0 ; d_idx < m_max_dim ; ++d_idx) {
137 fr[p_idx][d_idx] = points[p_idx][d_idx];
141 m_frames_size[0] = m_max_points;
145 m_current_slice = m_max_dim;
149 void wfg::free_wfg_members()
const
154 for(
unsigned int fr_idx = 0 ; fr_idx < m_n_frames ; ++fr_idx) {
155 for(
unsigned int p_idx = 0; p_idx < m_max_points ; ++p_idx) {
156 delete[] m_frames[fr_idx][p_idx];
158 delete[] m_frames[fr_idx];
161 delete[] m_frames_size;
165 void wfg::limitset(
const unsigned int begin_idx,
const unsigned int p_idx,
const unsigned int rec_level)
const
167 double **points = m_frames[rec_level - 1];
168 unsigned int n_points = m_frames_size[rec_level - 1];
172 double* p = points[p_idx];
173 double** frame = m_frames[rec_level];
175 for(
unsigned int idx = begin_idx; idx < n_points; ++idx) {
180 for(fitness_vector::size_type f_idx = 0; f_idx < m_current_slice; ++f_idx) {
181 frame[no_points][f_idx] = std::max(points[idx][f_idx], p[f_idx]);
184 std::vector<int> cmp_results;
185 cmp_results.resize(no_points);
186 double* s = frame[no_points];
191 for(
int q_idx = 0; q_idx < no_points; ++q_idx) {
192 cmp_results[q_idx] =
base::dom_cmp(s, frame[q_idx], m_current_slice);
193 if (cmp_results[q_idx] == base::DOM_CMP_B_DOMINATES_A) {
202 while(next < no_points) {
203 if( cmp_results[next] != base::DOM_CMP_A_DOMINATES_B && cmp_results[next] != base::DOM_CMP_A_B_EQUAL) {
205 for(
unsigned int d_idx = 0; d_idx < m_current_slice ; ++d_idx) {
206 frame[prev][d_idx] = frame[next][d_idx];
215 for(
unsigned int d_idx = 0; d_idx < m_current_slice ; ++d_idx) {
216 frame[prev][d_idx] = s[d_idx];
219 no_points = prev + 1;
223 m_frames_size[rec_level] = no_points;
227 double wfg::compute_hv(
const unsigned int rec_level)
const
229 double **points = m_frames[rec_level - 1];
230 unsigned int n_points = m_frames_size[rec_level - 1];
236 else if (n_points == 2) {
240 for(
unsigned int i=0;i<m_current_slice;++i) {
241 isect *= (m_refpoint[i] - std::max(points[0][i], points[1][i]));
247 if (m_current_slice == m_stop_dimension) {
249 if (m_stop_dimension == 2) {
251 return hv2d().compute(points, n_points, m_refpoint);
254 std::vector<fitness_vector> points_cpy;
255 points_cpy.reserve(n_points);
256 for(
unsigned int i = 0 ; i < n_points ; ++i) {
257 points_cpy.push_back(
fitness_vector(points[i], points[i] + m_current_slice));
261 hypervolume hv = hypervolume(points_cpy,
false);
262 hv.set_copy_points(
false);
263 return hv.compute(r_cpy);
269 std::sort(points, points + n_points, boost::bind(&wfg::cmp_points,
this, _1, _2));
275 if(rec_level >= m_n_frames) {
276 double** fr =
new double*[m_max_points];
277 for(
unsigned int i = 0 ; i < m_max_points ; ++i) {
278 fr[i]=
new double[m_current_slice];
280 m_frames[m_n_frames] = fr;
281 m_frames_size[m_n_frames] = 0;
285 for(
unsigned int p_idx = 0 ; p_idx < n_points ; ++p_idx) {
286 limitset(p_idx + 1, p_idx, rec_level);
288 H += fabs((points[p_idx][m_current_slice] - m_refpoint[m_current_slice]) * exclusive_hv(p_idx, rec_level));
295 double wfg::exclusive_hv(
const unsigned int p_idx,
const unsigned int rec_level)
const
300 if (m_frames_size[rec_level] == 1) {
302 }
else if (m_frames_size[rec_level] > 1) {
303 H -= compute_hv(rec_level + 1);
332 return "WFG algorithm";
base_ptr clone() const
Clone method.
static double volume_between(const fitness_vector &, const fitness_vector &, unsigned int=0)
Compute volume between two points.
void assert_minimisation(const std::vector< fitness_vector > &, const fitness_vector &) const
Assert that reference point dominates every other point from the set.
static int dom_cmp(double *, double *, unsigned int)
Dominance comparison method.
void verify_before_compute(const std::vector< fitness_vector > &, const fitness_vector &) const
Verify before compute method.
wfg(const unsigned int stop_dimension=2)
Constructor.
WFG hypervolume algorithm.
std::vector< double > fitness_vector
Fitness vector type.
double compute(std::vector< fitness_vector > &, const fitness_vector &) const
Compute hypervolume.
boost::shared_ptr< base > base_ptr
Base hypervolume algorithm class.
std::vector< double > contributions(std::vector< fitness_vector > &, const fitness_vector &) const
Contributions method.
std::string get_name() const
Algorithm name.