docs: def minimise_tables(routing_tables, target_lengths,
                      methods=(remove_default_entries, ordered_covering)):
      """Utility function which attempts to minimises routing tables for multiple
      chips.
  
      For each routing table supplied, this function will attempt to use the
      minimisation algorithms given (or some sensible default algorithms), trying
      each sequentially until a target number of routing entries has been
      reached.
  
      Parameters
      ----------
      routing_tables : {(x, y): [\
              :py:class:`~rig.routing_table.RoutingTableEntry`, ...], ...}
          Dictionary mapping chip co-ordinates to the routing tables associated
          with that chip. NOTE: This is the data structure as returned by
          :py:meth:`~rig.routing_table.routing_tree_to_tables`.
      target_lengths : int or {(x, y): int or None, ...} or None
          Maximum length of routing tables. If an integer this is assumed to be
          the maximum length for any table; if a dictionary then it is assumed to
          be a mapping from co-ordinate to maximum length (or None); if None then
          tables will be minimised as far as possible.
      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
      -------
      {(x, y): [:py:class:`~rig.routing_table.RoutingTableEntry`, ...], ...}
          Minimised routing tables, guaranteed to be at least as small as the
          table sizes specified by `target_lengths`.
  
      Raises
      ------
      MinimisationFailedError
          If no method can sufficiently minimise a table.
      """
      # Coerce the target lengths into the correct forms
      if not isinstance(target_lengths, dict):
          lengths = collections.defaultdict(lambda: target_lengths)
      else:
          lengths = target_lengths
  
      # Minimise the routing tables
      new_tables = dict()
      for chip, table in iteritems(routing_tables):
          # Try to minimise the table
          try:
              new_table = minimise_table(table, lengths[chip], methods)
          except MinimisationFailedError as exc:
              exc.chip = chip
              raise
  
          # Store the table if it isn't empty
          if new_table:
              new_tables[chip] = new_table
  
      return new_tables