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
Exemple #2
0
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
Exemple #3
0
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