def forward_selection(variables, train_model, score_model, verbose=True):
    """ Variable selection using forward selection 
    
    Input:
        variables: complete list of variables to consider in model building
        train_model: function that returns a fitted model for a given set of variables
        score_model: function that returns the score of a model; better models have lower scores
    
    Returns:
        (best_model, best_variables) 
    """
    best_variables = []
    best_model = train_model(best_variables)
    best_score = score_model(best_model, best_variables)
    if verbose:
        print('Variables: ' + ', '.join(variables))
        print('Start: score={:.2f}, constant'.format(best_score))
    while True:
        step = [(best_score, None, best_model)]
        for addVar in variables:
            if addVar in best_variables:
                continue
            step_var = list(best_variables)
            step_var.append(addVar)
            step_model = train_model(step_var)
            step_score = score_model(step_model, step_var)
            step.append((step_score, addVar, step_model))
        step.sort(key=lambda x: x[0])
        best_score, added_step, best_model = step[0]
        if verbose:
            print('Step: score={:.2f}, add {}'.format(best_score, added_step))
        if added_step is None:
            break
        best_variables.append(added_step)
    return best_model, best_variables
