def num_slopes_at_best(q, f, covered_intervals, uncovered_intervals=None):
    """
    Returns an upper bound on the final number of slopes,
    given current covered_intervals (and optionally, uncovered_intervals 
    that provides connected components of non-covered intervals).

    EXAMPLES::

        sage: from cutgeneratingfunctionology.igp import *
        sage: covered_intervals = [set([0,2])]
        sage: uncovered_intervals = [set([1]), set([3,4])]
        sage: num_slopes_at_best(5, 3, covered_intervals)
        3
        sage: num_slopes_at_best(5, 3, covered_intervals, uncovered_intervals)
        3
    """
    if uncovered_intervals is None:
        to_cover = set(list(range(0, (f + 1) // 2)) + list(range(f, (f + q +
            1) // 2)))
        for component in covered_intervals:
            to_cover -= component
        uncovered_num = len(to_cover)
    else:
        uncovered_num = len(uncovered_intervals)
    return uncovered_num + len(covered_intervals)
