def _optimise_with_method_on_func_caller(self, method, func_caller, worker_manager, max_capital, meth_options, reporter, *args, **kwargs): """ Run method on the function caller and return. """ meth_options.mode = 'asy' method = method.lower() if method == 'rand': _, _, history = random_optimiser_from_func_caller( func_caller, worker_manager, max_capital, meth_options.mode, options=meth_options, reporter=reporter, *args, **kwargs) elif method == 'ga': _, _, history = cp_ga_optimiser_from_proc_args( func_caller, func_caller.domain, worker_manager, max_capital, options=meth_options, reporter=reporter, *args, **kwargs) elif method.startswith('dragonfly'): is_mf = method.startswith( 'dragonfly-mf') # Check if multi-fidelity if method == 'dragonfly-mfexpdecay': meth_options.fidel_euc_kernel_type = 'expdecay' meth_options.fidel_int_kernel_type = 'expdecay' _, _, history = gpb_from_func_caller(func_caller, worker_manager, max_capital, is_mf=is_mf, mode=meth_options.mode, options=meth_options, reporter=reporter, *args, **kwargs) elif method.startswith('gpyopt'): history = self._optimise_with_gpyopt(func_caller, max_capital, meth_options) elif method.startswith('hyperopt'): history = self._optimise_with_hyperopt(func_caller, max_capital, meth_options) elif method.startswith('smac'): history = self._optimise_with_smac(func_caller, max_capital, meth_options) elif method.startswith('spearmint'): history = self._optimise_with_spearmint(func_caller, max_capital, meth_options, self.study_name) else: raise ValueError('Unknown method %s.' % (method)) return history
def maximise_function(func, domain, max_capital, config=None, options=None): """ Maximises a function 'func' over the domain 'domain'. Inputs: func: The function to be maximised. domain: The domain over which the function should be maximised, should be an instance of the Domain class in exd/domains.py. If domain is a list of the form [[l1, u1], [l2, u2], ...] where li < ui, then we will create a Euclidean domain with lower bounds li and upper bounds ui along each dimension. max_capital: The maximum capital (budget) available for optimisation. config: Contains configuration parameters that are typically returned by exd.cp_domain_utils.load_config_file. config can be None only if domain is a EuclideanDomain object. options: Additional hyper-parameters for optimisation. * Alternatively, domain could be None if config is either a path_name to a configuration file or has configuration parameters. Returns: opt_val: The maximum value found during the optimisatio procdure. opt_pt: The corresponding optimum point. history: A record of the optimisation procedure which include the point evaluated and the values at each time step. """ # Preprocess domain and config arguments raw_func = func domain, preproc_func_list, config, _ = _preprocess_arguments( domain, [func], config) func = preproc_func_list[0] # Load arguments depending on domain type if domain.get_type() == 'euclidean': func_caller = EuclideanFunctionCaller(func, domain, vectorised=False) else: func_caller = CPFunctionCaller( func, domain, raw_func=raw_func, domain_orderings=config.domain_orderings) # Create worker manager and function caller worker_manager = SyntheticWorkerManager(num_workers=1) # Optimise function here ----------------------------------------------------------- opt_val, opt_pt, history = gpb_from_func_caller(func_caller, worker_manager, max_capital, is_mf=False, options=options) # Post processing if domain.get_type() == 'euclidean' and config is None: opt_pt = func_caller.get_raw_domain_coords(opt_pt) history.curr_opt_points = [ func_caller.get_raw_domain_coords(pt) for pt in history.curr_opt_points ] history.query_points = [ func_caller.get_raw_domain_coords(pt) for pt in history.query_points ] else: opt_pt = get_raw_from_processed_via_config(opt_pt, config) history.curr_opt_points_raw = [ get_raw_from_processed_via_config(pt, config) for pt in history.curr_opt_points ] history.query_points_raw = [ get_raw_from_processed_via_config(pt, config) for pt in history.query_points ] return opt_val, opt_pt, history
def maximise_multifidelity_function(func, fidel_space, domain, fidel_to_opt, fidel_cost_func, max_capital, config=None, options=None): """ Maximises a multi-fidelity function 'func' over the domain 'domain' and fidelity space 'fidel_space'. Inputs: func: The function to be maximised. Takes two arguments func(z, x) where z is a member of the fidelity space and x is a member of the domain. fidel_space: The fidelity space from which the approximations are obtained. Should be an instance of the Domain class in exd/domains.py. If of the form [[l1, u1], [l2, u2], ...] where li < ui, then we will create a Euclidean domain with lower bounds li and upper bounds ui along each dimension. domain: The domain over which the function should be maximised, should be an instance of the Domain class in exd/domains.py. If domain is a list of the form [[l1, u1], [l2, u2], ...] where li < ui, then we will create a Euclidean domain with lower bounds li and upper bounds ui along each dimension. fidel_to_opt: The point at the fidelity space at which we wish to maximise func. max_capital: The maximum capital (budget) available for optimisation. config: Contains configuration parameters that are typically returned by exd.cp_domain_utils.load_config_file. config can be None only if domain is a EuclideanDomain object. options: Additional hyper-parameters for optimisation. * Alternatively, domain and fidelity space could be None if config is either a path_name to a configuration file or has configuration parameters. Returns: opt_val: The maximum value found during the optimisation procdure. opt_pt: The corresponding optimum point. history: A record of the optimisation procedure which include the point evaluated and the values at each time step. """ # Preprocess domain and config arguments raw_func = func fidel_space, domain, preproc_func_list, fidel_cost_func, fidel_to_opt, config, _ = \ _preprocess_multifidelity_arguments(fidel_space, domain, [func], fidel_cost_func, fidel_to_opt, config) func = preproc_func_list[0] # Load arguments and function caller if fidel_space.get_type() == 'euclidean' and domain.get_type( ) == 'euclidean': func_caller = EuclideanFunctionCaller(func, domain, vectorised=False, raw_fidel_space=fidel_space, fidel_cost_func=fidel_cost_func, raw_fidel_to_opt=fidel_to_opt) else: func_caller = CPFunctionCaller( func, domain, '', raw_func=raw_func, domain_orderings=config.domain_orderings, fidel_space=fidel_space, fidel_cost_func=fidel_cost_func, fidel_to_opt=fidel_to_opt, fidel_space_orderings=config.fidel_space_orderings) # Create worker manager worker_manager = SyntheticWorkerManager(num_workers=1) # Optimise function here ----------------------------------------------------------- opt_val, opt_pt, history = gpb_from_func_caller(func_caller, worker_manager, max_capital, is_mf=True, options=options) # Post processing if domain.get_type() == 'euclidean' and config is None: opt_pt = func_caller.get_raw_domain_coords(opt_pt) history.curr_opt_points = [ func_caller.get_raw_domain_coords(pt) for pt in history.curr_opt_points ] history.query_points = [ func_caller.get_raw_domain_coords(pt) for pt in history.query_points ] else: def _get_raw_from_processed_for_mf(fidel, pt): """ Returns raw point from processed point by accounting for the fact that a point could be None in the multi-fidelity setting. """ if fidel is None or pt is None: return None, None else: return get_raw_from_processed_via_config((fidel, pt), config) # Now re-write curr_opt_points opt_pt = _get_raw_from_processed_for_mf(fidel_to_opt, opt_pt)[1] history.curr_opt_points_raw = [ _get_raw_from_processed_for_mf(fidel_to_opt, pt)[1] for pt in history.curr_opt_points ] query_fidel_points_raw = [ _get_raw_from_processed_for_mf(fidel, pt) for fidel, pt in zip(history.query_fidels, history.query_points) ] history.query_fidels = [zx[0] for zx in query_fidel_points_raw] history.query_points = [zx[1] for zx in query_fidel_points_raw] return opt_val, opt_pt, history
def _optimise_with_method_on_func_caller(self, method, func_caller, worker_manager, max_capital, meth_options, reporter, *args, **kwargs): """ Run method on the function caller and return. """ meth_options.mode = 'asy' method = method.lower() if method == 'rand': _, _, history = random_optimiser.random_optimiser_from_func_caller( \ self.func_caller, self.worker_manager, self.max_capital, \ meth_options.mode, options=meth_options) elif method == 'mf_ucb': meth_options.acq = 'ucb' meth_options.mf_strategy = 'boca' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=True, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'add_mf_ucb': meth_options.acq = 'add_ucb' meth_options.mf_strategy = 'boca' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=True, options=meth_options, reporter=reporter, \ domain_add_max_group_size=0, *args, **kwargs) elif method in ['slice', 'post_sampling']: meth_options.acq = 'ucb-ei-ttei-add_ucb' meth_options.gpb_hp_tune_criterion = 'post_sampling' meth_options.gpb_post_hp_tune_method = 'slice' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'nuts': meth_options.gpb_hp_tune_criterion = 'post_sampling' meth_options.gpb_post_hp_tune_method = 'nuts' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'rand_exp_sampling': meth_options.acq = 'ucb-ei-ttei-add_ucb' meth_options.gpb_hp_tune_criterion = 'ml' meth_options.gpb_ml_hp_tune_opt = 'rand_exp_sampling' meth_options.kernel_type = 'se' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method in ['direct', 'ml']: meth_options.acq = 'ucb-ei-ttei-add_ucb' meth_options.gpb_hp_tune_criterion = 'ml' meth_options.gpb_ml_hp_tune_opt = 'direct' meth_options.kernel_type = 'se' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'ml+post_sampling': meth_options.acq = 'ucb-ei-ttei-add_ucb' meth_options.kernel_type = 'se' meth_options.gpb_hp_tune_criterion = 'ml-post_sampling' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'add-ei': meth_options.acq = 'ei' meth_options.use_additive_gp = True _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'esp-ei': meth_options.acq = 'ei' meth_options.kernel_type = 'esp' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'esp-ucb': meth_options.acq = 'ucb' meth_options.kernel_type = 'esp' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'add-add_ucb': meth_options.acq = 'add_ucb' meth_options.use_additive_gp = True _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'esp-se': meth_options.kernel_type = 'esp' meth_options.esp_kernel_type = 'se' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'esp-matern': meth_options.kernel_type = 'esp' meth_options.esp_kernel_type = 'matern' meth_options.esp_matern_nu = 2.5 _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'add-se': meth_options.use_additive_gp = True meth_options.kernel_type = 'se' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'add-matern': meth_options.use_additive_gp = True meth_options.kernel_type = 'matern' meth_options.matern_nu = 2.5 _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'se': meth_options.kernel_type = 'se' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'matern': meth_options.kernel_type = 'matern' meth_options.matern_nu = 2.5 _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method == 'ensemble-dfl': meth_options.acq_probs = 'uniform' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method in ['adaptive-ensemble-dfl', 'dragonfly']: _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method.startswith('dragonfly-mf'): if method == 'drafonfly-mf-exp': meth_options.fidel_kernel_type = 'expdecay' else: meth_options.fidel_kernel_type = 'se' _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=True, options=meth_options, reporter=reporter, \ *args, **kwargs) elif method in ['ei', 'ucb', 'add_ucb', 'pi', 'ttei', 'ts', 'ei-ucb-ttei-ts', 'ei-ucb-ttei-ts-add_ucb']: meth_options.acq = method _, _, history = gpb_from_func_caller(self.func_caller, self.worker_manager, \ self.max_capital, is_mf=False, options=meth_options, reporter=reporter, \ *args, **kwargs) # External packages elif method == 'pdoo': doo_func_to_max = _get_func_to_max_from_func_caller(self.func_caller) doo_obj = DOOFunction(doo_func_to_max, self.func_caller.domain.bounds) _, _, history = pdoo_wrap(doo_obj, self.max_capital, return_history=True) history = common_final_operations_for_all_external_packages(history, self.func_caller, meth_options) elif method == 'hyperopt': best, history = self._optimize_by_hyperopt_pkg(self.func_caller, self.max_capital, options=meth_options) print('Best eval point: {}'.format(best)) elif method == 'smac': history = self._optimize_by_smac_pkg(self.func_caller, self.max_capital, meth_options) elif method == 'spearmint': history = self._optimize_by_spearmint_pkg(self.func_caller, self.max_capital, meth_options) elif method == 'gpyopt': history = self._optimize_by_gpyopt_pkg(self.func_caller, self.max_capital, meth_options) # Final operations return history