def minimise_table(table, target_length,
                   methods=(remove_default_entries, ordered_covering)):
    """Apply different minimisation algorithms to minimise a single routing
    table.

    Parameters
    ----------
    table : [:py:class:`~rig.routing_table.RoutingTableEntry`, ...]
        Routing table to minimise.  NOTE: This is the data structure as
        returned by :py:meth:`~rig.routing_table.routing_tree_to_tables`.
    target_length : int or None
        Maximum length of the routing table. If None then all methods will be
        tried and the smallest achieved table will be returned.
    methods :
        Each method is tried in the order presented and the first to meet the
        required target length for a given chip is used. Consequently less
        computationally costly algorithms should be nearer the start of the
        list. The defaults will try to remove default routes
        (:py:meth:rig.routing_table.remove_default_routes.minimise) and then
        fall back on the ordered covering algorithm
        (:py:meth:rig.routing_table.ordered_covering.minimise).

    Returns
    -------
    [:py:class:`~rig.routing_table.RoutingTableEntry`, ...]
        Minimised routing table, guaranteed to be at least as small as
        `target_length`, or as small as possible if `target_length` is None.

    Raises
    ------
    MinimisationFailedError
        If no method can sufficiently minimise the table.
    """
    # Add a final method which checks the size of the table and returns it if
    # the size is correct. NOTE: This method will avoid running any other
    # minimisers if the table is already sufficiently small.
    methods = list(methods)
    methods.insert(0, _identity)

    if target_length is not None:
        best_achieved = len(table)

        # Try each minimiser in turn until the table is small enough
        for f in methods:
            try:
                # Minimise the table, if this fails a MinimisationFailedError
                # will be raised and the return will not be executed.
                new_table = f(table, target_length)
                return new_table
            except MinimisationFailedError as exc:
                # Store the best achieved final length
                if best_achieved is None or exc.final_length < best_achieved:
                    best_achieved = exc.final_length

        # The table must still be too large
        raise MinimisationFailedError(target_length, best_achieved)
    else:
        # Try all methods and return the smallest table
        return min((f(table, target_length) for f in methods), key=len)
Apply different minimisation algorithms to minimise a single routing
    table.

    Parameters
    ----------
    table : [:py:class:`~rig.routing_table.RoutingTableEntry`, ...]
        Routing table to minimise.  NOTE: This is the data structure as
        returned by :py:meth:`~rig.routing_table.routing_tree_to_tables`.
    target_length : int or None
        Maximum length of the routing table. If None then all methods will be
        tried and the smallest achieved table will be returned.
    methods :
        Each method is tried in the order presented and the first to meet the
        required target length for a given chip is used. Consequently less
        computationally costly algorithms should be nearer the start of the
        list. The defaults will try to remove default routes
        (:py:meth:rig.routing_table.remove_default_routes.minimise) and then
        fall back on the ordered covering algorithm
        (:py:meth:rig.routing_table.ordered_covering.minimise).

    Returns
    -------
    [:py:class:`~rig.routing_table.RoutingTableEntry`, ...]
        Minimised routing table, guaranteed to be at least as small as
        `target_length`, or as small as possible if `target_length` is None.

    Raises
    ------
    MinimisationFailedError
        If no method can sufficiently minimise the table.