code: def propose(self, n=1):
          
          proposed_params = []
  
          for i in range(n):
              # generate a list of random candidate vectors. If self.grid == True
              # each candidate will be a vector that has not been used before.
              candidate_params = self._create_candidates()
  
              # create_candidates() returns None when every grid point
              # has been tried
              if candidate_params is None:
                  return None
  
              # predict() returns a tuple of predicted values for each candidate
              predictions = self.predict(candidate_params)
  
              # acquire() evaluates the list of predictions, selects one,
              # and returns its index.
              idx = self._acquire(predictions)
  
              # inverse transform acquired hyperparameters
              # based on hyparameter type
              params = {}
              for i in range(candidate_params[idx, :].shape[0]):
                  inverse_transformed = self.tunables[i][1].inverse_transform(
                      candidate_params[idx, i]
                  )
                  params[self.tunables[i][0]] = inverse_transformed
              proposed_params.append(params)
  
          return params if n == 1 else proposed_params
docs: Use the trained model to propose a new set of parameters.
  
          Args:
              n (int, optional): number of candidates to propose
  
          Returns:
              Mapping of tunable name to proposed value. If called with n>1 then proposal is a list
                  of dictionaries.