Skip to content

Commit

Permalink
Added graph relabeling methods to coordinate objects
Browse files Browse the repository at this point in the history
    * chimera_coordinates:
         graph_to_linear
         graph_to_chimera
    * pegasus_coordinates:
         graph_to_linear
         graph_to_nice
         graph_to_pegasus
    * zephyr_coordinates:
         graph_to_linear
         graph_to_zephyr
  • Loading branch information
boothby committed Nov 29, 2021
1 parent 54c2d07 commit acd9696
Show file tree
Hide file tree
Showing 6 changed files with 274 additions and 2 deletions.
39 changes: 39 additions & 0 deletions dwave_networkx/generators/chimera.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,45 @@ def iter_linear_to_chimera_pairs(self, plist):
"""
return self._pair_repack(self.iter_linear_to_chimera, plist)

def graph_to_linear(self, g):
"""Return a copy of the graph g relabeled to have linear indices"""
labels = g.graph.get('labels')
if labels == 'int':
return g.copy()
elif labels == 'coordinate':
return chimera_graph(
g.graph['rows'],
n=g.graph['columns'],
t=g.graph['tile'],
node_list=self.iter_chimera_to_linear(g),
edge_list=self.iter_chimera_to_linear_pairs(g.edges),
data=g.graph['data'],
)
else:
raise ValueError(
f"Node labeling {labels} not recognized. Input must be generated by dwave_networkx.chimera_graph."
)

def graph_to_chimera(self, g):
"""Return a copy of the graph g relabeled to have chimera coordinates"""
labels = g.graph.get('labels')
if labels == 'int':
return chimera_graph(
g.graph['rows'],
n=g.graph['columns'],
t=g.graph['tile'],
node_list=self.iter_linear_to_chimera(g),
edge_list=self.iter_linear_to_chimera_pairs(g.edges),
data=g.graph['data'],
coordinates=True,
)
elif labels == 'coordinate':
return g.copy()
else:
raise ValueError(
f"Node labeling {labels} not recognized. Input must be generated by dwave_networkx.chimera_graph."
)


def linear_to_chimera(r, m, n=None, t=None):
"""Convert the linear index `r` into a chimera index.
Expand Down
80 changes: 80 additions & 0 deletions dwave_networkx/generators/pegasus.py
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,86 @@ def iter_nice_to_linear_pairs(self, nlist):
"""
return self._pair_repack(self.iter_nice_to_linear, nlist)

def graph_to_linear(self, g):
"""Return a copy of the graph g relabeled to have linear indices"""
labels = g.graph.get('labels')
if labels == 'int':
return g.copy()
elif labels == 'coordinate':
nodes = self.iter_pegasus_to_linear(g)
edges = self.iter_pegasus_to_linear_pairs(g.edges)
elif labels == 'nice':
nodes = self.iter_nice_to_linear(g)
edges = self.iter_nice_to_linear_pairs(g.edges)
else:
raise ValueError(
f"Node labeling {labels} not recognized. Input must be generated by dwave_networkx.pegasus_graph."
)

return pegasus_graph(
g.graph['rows'],
node_list=nodes,
edge_list=edges,
data=g.graph['data'],
offset_lists=(
g.graph["vertical_offsets"],
g.graph["horizontal_offsets"],
),
)

def graph_to_pegasus(self, g):
"""Return a copy of the graph g relabeled to have pegasus coordinates"""
labels = g.graph.get('labels')
if labels == 'int':
nodes = self.iter_linear_to_pegasus(g)
edges = self.iter_linear_to_pegasus_pairs(g.edges)
elif labels == 'coordinate':
return g.copy()
elif labels == 'nice':
nodes = self.iter_nice_to_pegasus(g)
edges = self.iter_nice_to_pegasus_pairs(g.edges)
else:
raise ValueError(
f"Node labeling {labels} not recognized. Input must be generated by dwave_networkx.pegasus_graph."
)

return pegasus_graph(
g.graph['rows'],
node_list=nodes,
edge_list=edges,
data=g.graph['data'],
coordinates=True,
offset_lists=(
g.graph["vertical_offsets"],
g.graph["horizontal_offsets"],
),
)

def graph_to_nice(self, g):
"""Return a copy of the graph p relabeled to have nice coordinates"""
labels = g.graph.get('labels')
if labels == 'int':
nodes = self.iter_linear_to_nice(g)
edges = self.iter_linear_to_nice_pairs(g.edges)
elif labels == 'coordinate':
nodes = self.iter_pegasus_to_nice(g)
edges = self.iter_pegasus_to_nice_pairs(g.edges)
elif labels == 'nice':
return g.copy()
else:
raise ValueError(
f"Node labeling {labels} not recognized. Input must be generated by dwave_networkx.pegasus_graph."
)

return pegasus_graph(
g.graph['rows'],
node_list=nodes,
edge_list=edges,
data=g.graph['data'],
nice_coordinates=True,
offsets_index = 0,
)

def int(self, q):
"""Deprecated alias of `pegasus_to_linear`."""
msg = ('pegasus_coordinates.int is deprecated and will be removed in '
Expand Down
43 changes: 43 additions & 0 deletions dwave_networkx/generators/zephyr.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,46 @@ def iter_linear_to_zephyr_pairs(self, plist):
to pairs of 5-term Zephyr coordinates.
"""
return self._pair_repack(self.iter_linear_to_zephyr, plist)

def graph_to_linear(self, g):
"""Return a copy of the graph g relabeled to have linear indices"""
labels = g.graph.get('labels')
if labels == 'int':
return g.copy()
elif labels == 'coordinate':
nodes = self.iter_zephyr_to_linear(g)
edges = self.iter_zephyr_to_linear_pairs(g.edges)
else:
raise ValueError(
f"Node labeling {labels} not recognized. Input must be generated by dwave_networkx.zephyr_graph."
)

return zephyr_graph(
g.graph['rows'],
t = g.graph['tile'],
node_list=nodes,
edge_list=edges,
data=g.graph['data'],
)

def graph_to_zephyr(self, g):
"""Return a copy of the graph g relabeled to have zephyr coordinates"""
labels = g.graph.get('labels')
if labels == 'int':
nodes = self.iter_linear_to_zephyr(g)
edges = self.iter_linear_to_zephyr_pairs(g.edges)
elif labels == 'coordinate':
return g.copy()
else:
raise ValueError(
f"Node labeling {labels} not recognized. Input must be generated by dwave_networkx.zephyr_graph."
)

return zephyr_graph(
g.graph['rows'],
t=g.graph['tile'],
node_list=nodes,
edge_list=edges,
data=g.graph['data'],
coordinates=True,
)
28 changes: 28 additions & 0 deletions tests/test_generator_chimera.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,31 @@ def test_nonsquare_coordinate_generator(self):

E = nx.relabel_nodes(H, coords.linear_to_chimera, copy=True)
self.assertEqual(set(map(frozenset, E.edges)), set(map(frozenset, G.edges)))


def test_graph_relabeling(self):
def graph_equal(g, h):
self.assertEqual(set(g), set(h))
self.assertEqual(
set(map(tuple, map(sorted, g.edges))),
set(map(tuple, map(sorted, g.edges)))
)
for v, d in g.nodes(data=True):
self.assertEqual(h.nodes[v], d)

coords = dnx.chimera_coordinates(3)
for data in True, False:
c3l = dnx.chimera_graph(3, data=data)
c3c = dnx.chimera_graph(3, data=data, coordinates=True)

graph_equal(c3l, coords.graph_to_linear(c3c))
graph_equal(c3l, coords.graph_to_linear(c3l))
graph_equal(c3c, coords.graph_to_chimera(c3l))
graph_equal(c3c, coords.graph_to_chimera(c3c))

h = dnx.chimera_graph(2)
del h.graph['labels']
with self.assertRaises(ValueError):
coords.graph_to_linear(h)
with self.assertRaises(ValueError):
coords.graph_to_chimera(h)
58 changes: 56 additions & 2 deletions tests/test_generator_pegasus.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,25 @@ def test_nice_coordinates(self):
pg = (t,) + p
qg = (t,) + q
self.assertTrue(G.has_edge(pg, qg))
n2p = dnx.pegasus_coordinates.nice_to_pegasus
p2n = dnx.pegasus_coordinates.pegasus_to_nice
coords = dnx.pegasus_coordinates(4)
n2p = coords.nice_to_pegasus
p2n = coords.pegasus_to_nice
n2l = coords.nice_to_linear
l2n = coords.linear_to_nice
for p in G.nodes():
self.assertEqual(p2n(n2p(p)), p)
self.assertEqual(l2n(n2l(p)), p)
self.assertTrue(H.has_node(p[1:]))

G = dnx.pegasus_graph(4)
for p in G.nodes():
self.assertEqual(n2l(l2n(p)), p)

G = dnx.pegasus_graph(4, coordinates=True)
for p in G.nodes():
self.assertEqual(n2p(p2n(p)), p)


def test_consistent_linear_nice_pegasus(self):
P4 = dnx.pegasus_graph(4, nice_coordinates=True)

Expand Down Expand Up @@ -190,6 +203,47 @@ def test_coordinate_subgraphs(self):
self.assertEqual(EG, sorted(map(sorted, coords.iter_pegasus_to_linear_pairs(Hn.edges()))))
self.assertEqual(EH, sorted(map(sorted, coords.iter_linear_to_pegasus_pairs(Gn.edges()))))

def test_graph_relabeling(self):
def graph_equal(g, h):
self.assertEqual(set(g), set(h))
self.assertEqual(
set(map(tuple, map(sorted, g.edges))),
set(map(tuple, map(sorted, g.edges)))
)
for v, d in g.nodes(data=True):
self.assertEqual(h.nodes[v], d)

coords = dnx.pegasus_coordinates(3)
nodes_nice = dnx.pegasus_graph(3, nice_coordinates=True)
nodes_linear = list(coords.iter_nice_to_linear(nodes_nice))
nodes_pegasus = list(coords.iter_nice_to_pegasus(nodes_nice))

for data in True, False:
p3l = dnx.pegasus_graph(3, data=data).subgraph(nodes_linear)
p3p = dnx.pegasus_graph(3, data=data, coordinates=True).subgraph(nodes_pegasus)
p3n = dnx.pegasus_graph(3, data=data, nice_coordinates=True)

graph_equal(p3l, coords.graph_to_linear(p3l))
graph_equal(p3l, coords.graph_to_linear(p3p))
graph_equal(p3l, coords.graph_to_linear(p3n))

graph_equal(p3p, coords.graph_to_pegasus(p3l))
graph_equal(p3p, coords.graph_to_pegasus(p3p))
graph_equal(p3p, coords.graph_to_pegasus(p3n))

graph_equal(p3n, coords.graph_to_nice(p3l))
graph_equal(p3n, coords.graph_to_nice(p3p))
graph_equal(p3n, coords.graph_to_nice(p3n))

h = dnx.pegasus_graph(2)
del h.graph['labels']
with self.assertRaises(ValueError):
coords.graph_to_nice(h)
with self.assertRaises(ValueError):
coords.graph_to_linear(h)
with self.assertRaises(ValueError):
coords.graph_to_pegasus(h)


class TestTupleFragmentation(unittest.TestCase):

Expand Down
28 changes: 28 additions & 0 deletions tests/test_generator_zephyr.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,31 @@ def test_coordinate_subgraphs(self):

self.assertEqual(EG, sorted(map(sorted, coords.iter_zephyr_to_linear_pairs(Hn.edges()))))
self.assertEqual(EH, sorted(map(sorted, coords.iter_linear_to_zephyr_pairs(Gn.edges()))))

def test_graph_relabeling(self):
def graph_equal(g, h):
self.assertEqual(set(g), set(h))
self.assertEqual(
set(map(tuple, map(sorted, g.edges))),
set(map(tuple, map(sorted, g.edges)))
)
for v, d in g.nodes(data=True):
self.assertEqual(h.nodes[v], d)

coords = dnx.zephyr_coordinates(3)
for data in True, False:
z3l = dnx.zephyr_graph(3, data=data)
z3c = dnx.zephyr_graph(3, data=data, coordinates=True)

graph_equal(z3l, coords.graph_to_linear(z3l))
graph_equal(z3l, coords.graph_to_linear(z3c))

graph_equal(z3c, coords.graph_to_zephyr(z3c))
graph_equal(z3c, coords.graph_to_zephyr(z3l))

h = dnx.zephyr_graph(2)
del h.graph['labels']
with self.assertRaises(ValueError):
coords.graph_to_linear(h)
with self.assertRaises(ValueError):
coords.graph_to_zephyr(h)

0 comments on commit acd9696

Please sign in to comment.