Source code for jgrapht.convert

from . import create_graph as _create_graph
from ._internals._anyhashableg import _is_anyhashable_graph


def _strip(elem):
    if isinstance(elem, str):
        return elem.strip('"')
    return elem


def _get_name(elem):
    return _strip(elem.get_name())


def _to_vertex_list(pydot_vertex):
    result = []
    if isinstance(pydot_vertex, str):
        result.append(_strip(pydot_vertex))
    else:
        for u in pydot_vertex["nodes"]:
            result.append(_strip(u))
    return result

def _parse_weight(attrs): 
    try:
        value = attrs.get('weight')
        return float(value) if value is not None else None
    except ValueError:
        return None


[docs]def from_pydot(graph): """Create a graph from a pydot graph. :param graph: a graph :type graph: pydot graph :returns: a new graph :rtype: jgrapht graph """ allows_parallel_edges = not graph.get_strict(None) allows_self_loops = not graph.get_strict(None) is_directed = graph.get_type() == "digraph" g = _create_graph( directed=is_directed, allowing_self_loops=allows_self_loops, weighted=True, any_hashable=True, ) name = _get_name(graph) if name != "": g.graph_attrs["name"] = name dotg_attrs = graph.get_attributes() if dotg_attrs: for k, v in dotg_attrs.items(): g.graph_attrs[k] = _strip(v) try: dotg_node_attrs = graph.get_node_defaults()[0] g_node_attrs = {} g.graph_attrs["vertex"] = g_node_attrs if dotg_node_attrs: for k, v in dotg_node_attrs.items(): g_node_attrs[k] = _strip(v) except (IndexError, TypeError): pass try: dotg_edge_attrs = graph.get_edge_defaults()[0] g_edge_attrs = {} g.graph_attrs["edge"] = g_edge_attrs if dotg_edge_attrs: for k, v in dotg_edge_attrs.items(): g_edge_attrs[k] = _strip(v) except (IndexError, TypeError): pass for dotv in graph.get_node_list(): dotv_name = _get_name(dotv) if dotv_name in ("graph", "node", "edge"): # skip nodes setting defaults continue g.add_vertex(dotv_name) for k, v in dotv.get_attributes().items(): g.vertex_attrs[dotv_name][k] = _strip(v) for dote in graph.get_edge_list(): ulist = _to_vertex_list(dote.get_source()) vlist = _to_vertex_list(dote.get_destination()) attrs = dote.get_attributes() for dotu in ulist: for dotv in vlist: if not g.contains_vertex(dotu): g.add_vertex(dotu) if not g.contains_vertex(dotv): g.add_vertex(dotv) e = g.add_edge(dotu, dotv) if 'weight' in attrs: weight_as_float = _parse_weight(attrs) if weight_as_float is not None: attrs['weight'] = weight_as_float else: attrs.pop('weight') g.edge_attrs[e].update(**attrs) return g
[docs]def to_pydot(graph): """Convert a graph to a pydot graph. :param graph: a graph :type graph: jgrapht graph :returns: a new graph :rtype: pydot graph """ try: import pydot except ImportError: raise ImportError("pydot required") graph_type = "digraph" if graph.type.directed else "graph" strict = graph.type.allowing_self_loops and graph.type.allowing_multiple_edges graph_name = "G" if _is_anyhashable_graph(graph): graph_name = graph.graph_attrs.get("name", graph_name) dotg = pydot.Dot(graph_name=graph_name, graph_type=graph_type, strict=strict) if _is_anyhashable_graph(graph): try: vertex_attrs = graph.graph_attrs["vertex"] dotg.set_node_defaults(**vertex_attrs) except KeyError: pass try: edge_attrs = graph.graph_attrs["edge"] dotg.set_edge_defaults(**edge_attrs) except KeyError: pass for v in graph.vertices: vattrs = {} if _is_anyhashable_graph(graph): vattrs.update({k: str(v) for k, v in graph.vertex_attrs[v].items()}) if 'name' in vattrs: vattrs.pop('name') dotv = pydot.Node(str(v), **vattrs) dotg.add_node(dotv) for e in graph.edges: u, v, weight = graph.edge_tuple(e) eattrs = {} if _is_anyhashable_graph(graph): eattrs.update({k: str(v) for k, v in graph.edge_attrs[e].items()}) elif graph.type.weighted: eattrs["weight"] = str(weight) dote = pydot.Edge(str(u), str(v), **eattrs) dotg.add_edge(dote) return dotg
[docs]def from_nx(graph, any_hashable=True): """Create a graph from a NetworkX graph. :param graph: a graph :type graph: nx graph :param any_hashable: if true the returned graph uses the same objects as the nx graph, otherwise integers are used. In the later case a renumbering is performed independently from any possible ordering in the original graph. :type any_hashable: boolean :returns: a new graph :type: jgrapht graph """ try: import networkx as nx except ImportError: raise ImportError("NetworkX required") is_directed = nx.is_directed(graph) is_weighted = any("weight" in data for u, v, data in graph.edges(data=True)) allowing_multiple_edges = isinstance(graph, (nx.MultiGraph, nx.MultiDiGraph)) result = _create_graph( directed=is_directed, weighted=is_weighted, allowing_self_loops=True, allowing_multiple_edges=allowing_multiple_edges, any_hashable=any_hashable, ) if any_hashable: # copy graph topology and attributes result.graph_attrs.update(**graph.graph) for v in graph.nodes: result.add_vertex(vertex=v) result.vertex_attrs[v].update(**graph.nodes[v]) try: for u, v, k in graph.edges(keys=True): e = result.add_edge(u, v) result.edge_attrs[e].update(**graph.edges[u,v,k]) except TypeError: for u, v in graph.edges(): e = result.add_edge(u, v) result.edge_attrs[e].update(**graph.edges[u,v]) else: # copy graph topology only vmap = {} for v in graph.nodes: vmap[v] = result.add_vertex() for u, v, d in graph.edges(data=True): if 'weight' in d: result.add_edge(vmap[u], vmap[v], weight=d['weight']) else: result.add_edge(vmap[u], vmap[v]) return result
[docs]def to_nx(graph): """Create a NetworkX graph from a graph. :param graph: a graph :type graph: jgrapht graph :returns: a new graph :rtype: NetworkX graph """ try: import networkx as nx except ImportError: raise ImportError("NetworkX required") if graph.type.directed: if graph.type.allowing_multiple_edges: result = nx.MultiDiGraph() else: result = nx.DiGraph() else: if graph.type.allowing_multiple_edges: result = nx.MultiGraph() else: result = nx.Graph() if _is_anyhashable_graph(graph): # copy topology and attributes result.graph.update(**graph.graph_attrs) for v in graph.vertices: result.add_node(v) result.nodes[v].update(**graph.vertex_attrs[v]) if graph.type.allowing_multiple_edges: if graph.type.weighted: for e in graph.edges: u = graph.edge_source(e) v = graph.edge_target(e) w = graph.get_edge_weight(e) k = result.add_edge(u, v, weight=w) result.edges[u, v, k].update(**graph.edge_attrs[e]) else: for e in graph.edges: u = graph.edge_source(e) v = graph.edge_target(e) k = result.add_edge(u, v) result.edges[u, v, k].update(**graph.edge_attrs[e]) else: if graph.type.weighted: for e in graph.edges: u = graph.edge_source(e) v = graph.edge_target(e) w = graph.get_edge_weight(e) result.add_edge(u, v, weight=w) result.edges[u, v].update(**graph.edge_attrs[e]) else: for e in graph.edges: u = graph.edge_source(e) v = graph.edge_target(e) result.add_edge(u, v) result.edges[u, v].update(**graph.edge_attrs[e]) else: # copy topology for v in graph.vertices: result.add_node(v) if graph.type.weighted: for e in graph.edges: u = graph.edge_source(e) v = graph.edge_target(e) w = graph.get_edge_weight(e) result.add_edge(u, v, weight=w) else: for e in graph.edges: u = graph.edge_source(e) v = graph.edge_target(e) result.add_edge(u, v) return result