def METHOD_NAME(dataset, config, tuner, log):
    """
    Using the given tuner, tune a random forest within the given time constraint.
    This function uses cross validation score as the feedback score to the tuner. 
    The search space on which tuners search on is defined above empirically as a global variable.
    """
    limit_type, trial_limit = config.framework_params['limit_type'], None
    if limit_type == 'ntrials':
        trial_limit = int(config.framework_params['trial_limit'])
    X_train, X_test = preprocess_mlp(dataset, log)
    y_train, y_test = dataset.train.y, dataset.test.y
    is_classification = config.type == 'classification'
    estimator = MLPClassifier if is_classification else MLPRegressor
    best_score, best_params, best_model = None, None, None
    score_higher_better = True
    tuner.update_search_space(SEARCH_SPACE)    
    start_time = time.time()
    trial_count = 0
    intermediate_scores = []
    intermediate_best_scores = []           # should be monotonically increasing 
    while True:
        try:            
            param_idx, cur_params = tuner.generate_parameters()
            if cur_params is not None and cur_params != {}:
                trial_count += 1
                train_params = cur_params.copy()
                if 'TRIAL_BUDGET' in cur_params:
                    train_params.pop('TRIAL_BUDGET')
                log.info("Trial {}: \n{}\n".format(param_idx, train_params))
                cur_model = estimator(random_state=config.seed, **train_params)
                # Here score is the output of score() from the estimator
                cur_score = cross_val_score(cur_model, X_train, y_train)
                cur_score = np.mean(cur_score)
                if np.isnan(cur_score):
                    cur_score = 0
                log.info("Score: {}\n".format(cur_score))
                if best_score is None or (score_higher_better and cur_score > best_score) or (not score_higher_better and cur_score < best_score):
                    best_score, best_params, best_model = cur_score, cur_params, cur_model    
                intermediate_scores.append(cur_score)
                intermediate_best_scores.append(best_score)
                tuner.receive_trial_result(param_idx, cur_params, cur_score)
            if limit_type == 'time':
                current_time = time.time()
                elapsed_time = current_time - start_time
                if elapsed_time >= config.max_runtime_seconds:
                    break
            elif limit_type == 'ntrials':
                if trial_count >= trial_limit:
                    break
        except:
            break
    # This line is required to fully terminate some advisors
    tuner.handle_terminate()
    log.info("Tuning done, the best parameters are:\n{}\n".format(best_params))
    # retrain on the whole dataset 
    with Timer() as training:
        best_model.fit(X_train, y_train)     
    predictions = best_model.predict(X_test)
    probabilities = best_model.predict_proba(X_test) if is_classification else None
    return probabilities, predictions, training, y_test, intermediate_scores, intermediate_best_scores