code: def transitive_reduction(G):
      
      H = G.copy()
      for a, b, w in G.edges_iter(data=True):
          # Try deleting the edge, see if we still have a path
          # between the vertices
          H.remove_edge(a, b)
          if not nx.has_path(H, a, b):  # we shouldn't have deleted it
              H.add_edge(a, b, w)
      return H
docs: Returns a transitive reduction of a graph.  The original graph
      is not modified.
  
      A transitive reduction H of G has a path from x to y if and
      only if there was a path from x to y in G.  Deleting any edge
      of H destroys this property.  A transitive reduction is not
      unique in general.  A transitive reduction has the same
      transitive closure as the original graph.
  
      A transitive reduction of a complete graph is a tree.  A
      transitive reduction of a tree is itself.
  
      >>> G = nx.DiGraph([(1, 2), (1, 3), (2, 3), (2, 4), (3, 4)])
      >>> H = transitive_reduction(G)
      >>> H.edges()
      [(1, 2), (2, 3), (3, 4)]