def METHOD_NAME(self, max_evals: int = -1, timeout: int = None):
    """Execute the search algorithm.
    Args:
        max_evals (int, optional): The maximum number of evaluations of the run function to perform before stopping the search. Defaults to ``-1``, will run indefinitely.
        timeout (int, optional): The time budget (in seconds) of the search before stopping. Defaults to ``None``, will not impose a time budget.
    Returns:
        DataFrame: a pandas DataFrame containing the evaluations performed or ``None`` if the search could not evaluate any configuration.
    """
    self._set_timeout(timeout)
    # save the search call arguments for the context
    self._call_args.append({"timeout": timeout, "max_evals": max_evals})
    # save the context in the log folder
    self.dump_context()
    # init tqdm callback
    if max_evals > 1:
        for cb in self._evaluator._callbacks:
            if isinstance(cb, TqdmCallback):
                cb.set_max_evals(max_evals)
    try:
        self._search(max_evals, timeout)
    except SearchTerminationError:
        if "saved_keys" in dir(self):
            self._evaluator.dump_evals(saved_keys=self.saved_keys)
        else:
            self._evaluator.dump_evals(log_dir=self._log_dir)
    path_results = os.path.join(self._log_dir, "results.csv")
    if not (os.path.exists(path_results)):
        logging.warning(f"Could not find results file at {path_results}!")
        return None
    self.extend_results_with_pareto_efficient(path_results)
    df_results = pd.read_csv(path_results)
    return df_results