'Return a directed representation of the graph.
Returns
G : MultiDiGraph
A directed graph with the same name, same nodes, and with
each edge (u, v, data) replaced by two directed edges
(u, v, data) and (v, u, data).
Notes
This returns a "deepcopy" of the edge, node, and
graph attributes which attempts to completely copy
all of the data and references.
This is in contrast to the similar D=DiGraph(G) which returns a
shallow copy of the data.
See the Python copy module for more information on shallow
and deep copies, http://docs.python.org/library/copy.html.
Warning: If you have subclassed MultiGraph to use dict-like objects
in the data structure, those changes do not transfer to the
MultiDiGraph created by this method.
Examples
>>> G = nx.Graph()   # or MultiGraph, etc
>>> G.add_edge(0, 1)
>>> H = G.to_directed()
>>> list(H.edges())
[(0, 1), (1, 0)]
If already directed, return a (deep) copy
>>> G = nx.DiGraph()   # or MultiDiGraph, etc
>>> G.add_edge(0, 1)
>>> H = G.to_directed()
>>> list(H.edges())
[(0, 1)]'

def to_directed(self):

    from networkx.classes.multidigraph import MultiDiGraph
    G = MultiDiGraph()
    G.add_nodes_from(self)
    G.add_edges_from(((u, v, key, deepcopy(datadict)) for (u, nbrs) in self.adjacency() for (v, keydict) in nbrs.items() for (key, datadict) in keydict.items()))
    G.graph = deepcopy(self.graph)
    G._node = deepcopy(self._node)
    return G
