docs: 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)