Source code for autooed.mobo.selection.hvi

'''
Hypervolume improvement selection.
'''

import numpy as np
from pymoo.factory import get_performance_indicator

from autooed.utils.pareto import find_pareto_front
from autooed.mobo.selection.base import Selection


[docs]class HypervolumeImprovement(Selection): ''' Selection based on Hypervolume improvement. '''
[docs] def _select(self, X_candidate, Y_candidate, X, Y, batch_size): pred_pset, pred_pfront = X_candidate, Y_candidate curr_pfront = find_pareto_front(Y) ref_point = np.max(np.vstack([Y_candidate, Y]), axis=0) hv = get_performance_indicator('hv', ref_point=ref_point) idx_choices = np.ma.array(np.arange(len(pred_pset)), mask=False) # mask array for index choices next_batch_indices = [] # greedily select indices that maximize hypervolume contribution for _ in range(batch_size): curr_hv = hv.calc(curr_pfront) max_hv_contrib = 0. max_hv_idx = -1 for idx in idx_choices.compressed(): # calculate hypervolume contribution new_hv = hv.calc(np.vstack([curr_pfront, pred_pfront[idx]])) hv_contrib = new_hv - curr_hv if hv_contrib > max_hv_contrib: max_hv_contrib = hv_contrib max_hv_idx = idx if max_hv_idx == -1: # if all candidates have no hypervolume contribution, just randomly select one max_hv_idx = np.random.choice(idx_choices.compressed()) idx_choices.mask[max_hv_idx] = True # mask as selected curr_pfront = np.vstack([curr_pfront, pred_pfront[max_hv_idx]]) # add to current pareto front next_batch_indices.append(max_hv_idx) next_batch_indices = np.array(next_batch_indices) X_next = pred_pset[next_batch_indices] return X_next