Skip to content

Commit afe2230

Browse files
authored
Conversion of objects to/from other libraries (#242)
1 parent c94925d commit afe2230

3 files changed

Lines changed: 657 additions & 0 deletions

File tree

src/igraph/__init__.py

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,6 +1742,182 @@ def maximum_bipartite_matching(self, types="type", weights=None, eps=None):
17421742
#############################################
17431743
# Auxiliary I/O functions
17441744

1745+
def to_networkx(self):
1746+
"""Converts the graph to networkx format"""
1747+
import networkx as nx
1748+
1749+
# Graph: decide on directness and mutliplicity
1750+
if any(self.is_multiple()):
1751+
if self.is_directed():
1752+
klass = nx.MultiDiGraph
1753+
else:
1754+
klass = nx.MultiGraph
1755+
else:
1756+
if self.is_directed():
1757+
klass = nx.DiGraph
1758+
else:
1759+
klass = nx.Graph
1760+
1761+
# Graph attributes
1762+
kw = {x: self[x] for x in self.attributes()}
1763+
g = klass(**kw)
1764+
1765+
# Nodes and node attributes
1766+
for i, v in enumerate(self.vs):
1767+
g.add_node(i, **v.attributes())
1768+
1769+
# Edges and edge attributes
1770+
for edge in self.es:
1771+
g.add_edge(edge.source, edge.target, **edge.attributes())
1772+
1773+
return g
1774+
1775+
@classmethod
1776+
def from_networkx(klass, g):
1777+
"""Converts the graph from networkx
1778+
1779+
Vertex names will be converted to "_nx_name" attribute and the vertices
1780+
will get new ids from 0 up (as standard in igraph).
1781+
1782+
@param g: networkx Graph or DiGraph
1783+
"""
1784+
import networkx as nx
1785+
1786+
# Graph attributes
1787+
gattr = dict(g.graph)
1788+
1789+
# Nodes
1790+
vnames = list(g.nodes)
1791+
vattr = {'_nx_name': vnames}
1792+
vcount = len(vnames)
1793+
vd = {v: i for i, v in enumerate(vnames)}
1794+
1795+
# NOTE: we do not need a special class for multigraphs, it is taken
1796+
# care for at the edge level rather than at the graph level.
1797+
graph = klass(
1798+
n=vcount,
1799+
directed=g.is_directed(),
1800+
graph_attrs=gattr,
1801+
vertex_attrs=vattr)
1802+
1803+
# Node attributes
1804+
for v, datum in g.nodes.data():
1805+
for key, val in datum.items():
1806+
graph.vs[vd[v]][key] = val
1807+
1808+
# Edges and edge attributes
1809+
# NOTE: we need to do both together to deal well with multigraphs
1810+
# Each e might have a length of 2 (graphs) or 3 (multigraphs, the
1811+
# third element is the "color" of the edge)
1812+
for e, (_, _, datum) in zip(g.edges, g.edges.data()):
1813+
eid = graph.add_edge(vd[e[0]], vd[e[1]])
1814+
for key, val in datum.items():
1815+
eid[key] = val
1816+
1817+
return graph
1818+
1819+
def to_graph_tool(
1820+
self,
1821+
graph_attributes=None,
1822+
vertex_attributes=None,
1823+
edge_attributes=None):
1824+
"""Converts the graph to graph-tool
1825+
1826+
@param graph_attributes: dictionary of graph attributes to transfer.
1827+
Keys are attributes from the graph, values are data types (see
1828+
below). C{None} means no graph attributes are transferred.
1829+
@param vertex_attributes: dictionary of vertex attributes to transfer.
1830+
Keys are attributes from the vertices, values are data types (see
1831+
below). C{None} means no vertex attributes are transferred.
1832+
@param edge_attributes: dictionary of edge attributes to transfer.
1833+
Keys are attributes from the edges, values are data types (see
1834+
below). C{None} means no vertex attributes are transferred.
1835+
1836+
Data types: graph-tool only accepts specific data types. See the
1837+
following web page for a list:
1838+
1839+
https://graph-tool.skewed.de/static/doc/quickstart.html
1840+
1841+
NOTE: because of the restricted data types in graph-tool, vertex and
1842+
edge attributes require to be type-consistent across all vertices or
1843+
edges. If you set the property for only some vertices/edges, the other
1844+
will be tagged as None in python-igraph, so they can only be converted
1845+
to graph-tool with the type 'object' and any other conversion will
1846+
fail.
1847+
"""
1848+
import graph_tool as gt
1849+
1850+
# Graph
1851+
g = gt.Graph(directed=self.is_directed())
1852+
1853+
# Nodes
1854+
vc = self.vcount()
1855+
g.add_vertex(vc)
1856+
1857+
# Graph attributes
1858+
if graph_attributes is not None:
1859+
for x, dtype in graph_attributes.items():
1860+
# Strange syntax for setting internal properties
1861+
gprop = g.new_graph_property(str(dtype))
1862+
g.graph_properties[x] = gprop
1863+
g.graph_properties[x] = self[x]
1864+
1865+
# Vertex attributes
1866+
if vertex_attributes is not None:
1867+
for x, dtype in vertex_attributes.items():
1868+
# Create a new vertex property
1869+
g.vertex_properties[x] = g.new_vertex_property(str(dtype))
1870+
# Fill the values from the igraph.Graph
1871+
for i in range(vc):
1872+
g.vertex_properties[x][g.vertex(i)] = self.vs[i][x]
1873+
1874+
# Edges and edge attributes
1875+
if edge_attributes is not None:
1876+
for x, dtype in edge_attributes.items():
1877+
g.edge_properties[x] = g.new_edge_property(str(dtype))
1878+
for edge in self.es:
1879+
e = g.add_edge(edge.source, edge.target)
1880+
if edge_attributes is not None:
1881+
for x, dtype in edge_attributes.items():
1882+
prop = edge.attributes().get(x, None)
1883+
g.edge_properties[x][e] = prop
1884+
1885+
return g
1886+
1887+
@classmethod
1888+
def from_graph_tool(klass, g):
1889+
"""Converts the graph from graph-tool
1890+
1891+
@param g: graph-tool Graph
1892+
"""
1893+
# Graph attributes
1894+
gattr = dict(g.graph_properties)
1895+
1896+
# Nodes
1897+
vcount = g.num_vertices()
1898+
1899+
# Graph
1900+
graph = klass(
1901+
n=vcount,
1902+
directed=g.is_directed(),
1903+
graph_attrs=gattr)
1904+
1905+
# Node attributes
1906+
for key, val in g.vertex_properties.items():
1907+
prop = val.get_array()
1908+
for i in range(vcount):
1909+
graph.vs[i][key] = prop[i]
1910+
1911+
# Edges
1912+
# NOTE: the order the edges are put in is necessary to set the
1913+
# attributes later on
1914+
for e in g.edges():
1915+
edge = graph.add_edge(int(e.source()), int(e.target()))
1916+
for key, val in g.edge_properties.items():
1917+
edge[key] = val[e]
1918+
1919+
return graph
1920+
17451921
def write_adjacency(self, f, sep=" ", eol="\n", *args, **kwds):
17461922
"""Writes the adjacency matrix of the graph to the given file
17471923

0 commit comments

Comments
 (0)