From a60d9bd391b925c5caea425cd58353fa9dc7ea2e Mon Sep 17 00:00:00 2001 From: Jack Raymond <10591246+jackraymond@users.noreply.github.com> Date: Fri, 15 Jul 2022 13:18:51 -0700 Subject: [PATCH 01/15] edgelist nodelist docstring and functionality update for chimera --- dwave_networkx/generators/chimera.py | 52 +++++++++++++++++++++++----- tests/test_generator_chimera.py | 46 ++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 8 deletions(-) diff --git a/dwave_networkx/generators/chimera.py b/dwave_networkx/generators/chimera.py index 11a9fe2f..3994bb86 100644 --- a/dwave_networkx/generators/chimera.py +++ b/dwave_networkx/generators/chimera.py @@ -35,7 +35,17 @@ ] -def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_list=None, data=True, coordinates=False): +def _add_compatible_edges(G, edge_list): + # Slow when edge_list is large, but clear (non-defaulted behaviour, so fine): + if edge_list is not None: + if not all([G.has_edge(*e) for e in edge_list]): + raise ValueError("edge_list contains edges incompatible with a " + "fully yielded graph of the requested topology") + if len(edge_list) < G.number_of_edges(): + G.remove_edges_from(list(G.edges)) + G.add_edges_from(edge_list) + +def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_list=None, data=True, coordinates=False, check_node_list=False, check_edge_list=False): """Creates a Chimera lattice of size (m, n, t). Parameters @@ -51,12 +61,18 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis with the new graph. Usually used to set the type of the graph. node_list : iterable (optional, default None) Iterable of nodes in the graph. If None, calculated - from (m, n, t). Note that this list is used to remove nodes, - so any nodes specified not in ``range(m * n * 2 * t)`` are not added. + from (``m``, ``n``, ``t``). The node_list should match the requested + coordinate system and topology bounds; by default values should + be integer-labeled in ``range(m * n * t * 2)``. Nodes incompatible + with the requested topology are accepted by defaulted. edge_list : iterable (optional, default None) - Iterable of edges in the graph. If None, edges are - generated as described below. The nodes in each edge must be - integer-labeled in ``range(m * n * t * 2)``. + Iterable of edges in the graph. If None, calculated + from (``m``, ``n``, ``t``) as described below. The edge_list should + consist of 2-tuples of nodes that match the requested + coordinate system and topology bounds. Edges incompatible + with the requested topology are accepted by default. Nodes + present in the edge_list, but absent in the node_list are + removed. data : bool (optional, default True) If True, each node has a `chimera_index attribute`. The attribute is a 4-tuple Chimera index @@ -65,6 +81,16 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis If True, node labels are 4-tuples, equivalent to the chimera_index attribute as below. In this case, the `data` parameter controls the existence of a `linear_index attribute`, which is an int. + check_node_list : bool (optional, default False) + If True, the node_list elements are checked for compatibility with + the graph topology and node labeling conventions, an error is thrown + if any node is incompatible. In other words, only node_lists that + specify subgraphs of the default (full yield) graph are permitted. + check_edge_list : bool (optional, default False) + If True, the edge_list elements are checked for compatibility with + the graph topology and node labeling conventions, an error is thrown + if any edge is incompatible. In other words, only edge_lists that + specify subgraphs of the default (full yield) graph are permitted. Returns ------- @@ -139,7 +165,7 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis max_size = m * n * 2 * t # max number of nodes G can have - if edge_list is None: + if edge_list is None or check_edge_list is True: if coordinates: # tile edges G.add_edges_from(((i, j, 0, k0), (i, j, 1, k1)) @@ -180,13 +206,23 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis for i in range(t) for j in range(i, ni, hoff) for k in range(j, mi - voff, voff)) + if edge_list is not None: + _add_compatible_edges(G, edge_list) + else: G.add_edges_from(edge_list) if node_list is not None: nodes = set(node_list) G.remove_nodes_from(set(G) - nodes) - G.add_nodes_from(nodes) # for singleton nodes + if check_node_list: + if G.number_of_nodes() != len(nodes): + raise ValueError("node_list contains nodes incompatible with " + "the specified topology and node-labeling " + "convention.") + + else: + G.add_nodes_from(nodes) # for singleton nodes if data: if coordinates: diff --git a/tests/test_generator_chimera.py b/tests/test_generator_chimera.py index bcab14dc..dcb919f3 100644 --- a/tests/test_generator_chimera.py +++ b/tests/test_generator_chimera.py @@ -282,3 +282,49 @@ def check_subgraph_mapping(f, g, h): covered.update(map(f, source)) self.assertEqual(covered, set(target)) + + def test_edge_list(self): + m=2 + n=3 + t=4 + G = dnx.chimera_graph(m, n, t) + edge_list = list(G.edges) + #Valid (full) edge_list + G = dnx.chimera_graph(m, n, t, edge_list=edge_list, + check_edge_list=True) + + #Valid edge_list in coordinate system + edge_list = [((0,0,0,0),(0,0,1,0))] + G = dnx.chimera_graph(m, n, t, edge_list=edge_list, + check_node_list=True, coordinates=True) + + with self.assertRaises(ValueError): + #Invalid edge_list (0,1) is a vertical-vertical coupler. + edge_list = [(0,t),(0,1)] + G = dnx.chimera_graph(m, n, t, edge_list=edge_list, + check_edge_list=True) + + def test_node_list(self): + m=4 + n=3 + t=2 + G = dnx.chimera_graph(m,n,t) + #Valid (full) node_list + node_list = list(G.nodes) + G = dnx.chimera_graph(m, n, t, node_list=node_list, + check_node_list=True) + #Valid node_list in coordinate system + node_list = [(0,0,0,0)] + G = dnx.chimera_graph(m, n, t, node_list=node_list, + check_node_list=True, coordinates=True) + with self.assertRaises(ValueError): + #Invalid node_list + node_list = [0,m*n*t*2] + G = dnx.chimera_graph(m, n, t, node_list=node_list, + check_node_list=True) + with self.assertRaises(ValueError): + #node is valid, but not in the requested coordinate system + node_list = [0] + G = dnx.chimera_graph(m, n, t, node_list=node_list, + check_node_list=True, coordinates=True) + From 8cc8007b8e6a18a33a9558565c8d6e409e35e5b1 Mon Sep 17 00:00:00 2001 From: Jack Raymond <10591246+jackraymond@users.noreply.github.com> Date: Fri, 15 Jul 2022 15:08:17 -0700 Subject: [PATCH 02/15] Pegasus and Zephyr node_list and edge_list behaviour documented and regularized --- dwave_networkx/generators/chimera.py | 21 +++++----- dwave_networkx/generators/pegasus.py | 58 ++++++++++++++++++++++------ dwave_networkx/generators/zephyr.py | 48 ++++++++++++++++------- tests/test_generator_pegasus.py | 57 +++++++++++++++++++++++++++ tests/test_generator_zephyr.py | 44 +++++++++++++++++++++ 5 files changed, 194 insertions(+), 34 deletions(-) diff --git a/dwave_networkx/generators/chimera.py b/dwave_networkx/generators/chimera.py index 3994bb86..1799bfb3 100644 --- a/dwave_networkx/generators/chimera.py +++ b/dwave_networkx/generators/chimera.py @@ -45,7 +45,8 @@ def _add_compatible_edges(G, edge_list): G.remove_edges_from(list(G.edges)) G.add_edges_from(edge_list) -def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_list=None, data=True, coordinates=False, check_node_list=False, check_edge_list=False): +def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_list=None, + data=True, coordinates=False, check_node_list=False, check_edge_list=False): """Creates a Chimera lattice of size (m, n, t). Parameters @@ -60,18 +61,18 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis If provided, this graph is cleared of nodes and edges and filled with the new graph. Usually used to set the type of the graph. node_list : iterable (optional, default None) - Iterable of nodes in the graph. If None, calculated - from (``m``, ``n``, ``t``). The node_list should match the requested - coordinate system and topology bounds; by default values should - be integer-labeled in ``range(m * n * t * 2)``. Nodes incompatible - with the requested topology are accepted by defaulted. + Iterable of nodes in the graph. If None, calculated from (``m``, ``n``, ``t``) + and ``coordinates``. The nodes should be compatible with the requested + coordinate system and topology bounds; by default integer-labeled + in :code:`range(m * n * t * 2)`. Nodes incompatible + with the requested topology are accepted by default. edge_list : iterable (optional, default None) Iterable of edges in the graph. If None, calculated - from (``m``, ``n``, ``t``) as described below. The edge_list should - consist of 2-tuples of nodes that match the requested - coordinate system and topology bounds. Edges incompatible + from (``m``, ``n``, ``t``) and ``coordinates`` as described below. + Edges should be 2-tuples of nodes that match the + requested coordinate system and topology bounds. Edges incompatible with the requested topology are accepted by default. Nodes - present in the edge_list, but absent in the node_list are + present in the ``edge_list``, but absent in the ``node_list`` are removed. data : bool (optional, default True) If True, each node has a diff --git a/dwave_networkx/generators/pegasus.py b/dwave_networkx/generators/pegasus.py index b570614c..da240d94 100644 --- a/dwave_networkx/generators/pegasus.py +++ b/dwave_networkx/generators/pegasus.py @@ -31,9 +31,19 @@ ] +def _add_compatible_edges(G, edge_list): + # Slow when edge_list is large, but clear (non-defaulted behaviour, so fine): + if edge_list is not None: + if not all([G.has_edge(*e) for e in edge_list]): + raise ValueError("edge_list contains edges incompatible with a " + "fully yielded graph of the requested topology") + if len(edge_list) < G.number_of_edges(): + G.remove_edges_from(list(G.edges)) + G.add_edges_from(edge_list) + def pegasus_graph(m, create_using=None, node_list=None, edge_list=None, data=True, offset_lists=None, offsets_index=None, coordinates=False, fabric_only=True, - nice_coordinates=False): + nice_coordinates=False, check_node_list=False, check_edge_list=False): """ Creates a Pegasus graph with size parameter `m`. @@ -44,14 +54,21 @@ def pegasus_graph(m, create_using=None, node_list=None, edge_list=None, data=Tru create_using : Graph, optional (default None) If provided, this graph is cleared of nodes and edges and filled with the new graph. Usually used to set the type of the graph. - node_list : iterable, optional (default None) - Iterable of nodes in the graph. If None, calculated from `m`. - Note that this list is used to remove nodes, so any nodes specified - not in ``range(24 * m * (m-1))`` are not added. - edge_list : iterable, optional (default None) - Iterable of edges in the graph. If None, edges are generated as - described below. The nodes in each edge must be integer-labeled in - ``range(24 * m * (m-1))``. + node_list : iterable (optional, default None) + Iterable of nodes in the graph. If None, calculated + from ``m``,``fabric_only``, ``nice_coordinates`` and + ``coordinates`` as described below. The nodes should be compatible + with the requested coordinate system and topology bounds; by + default integer-labeled in :code:`range(m * (m-1) * 24)`. Nodes + incompatible with the requested topology are accepted by default. + edge_list : iterable (optional, default None) + Iterable of edges in the graph. If None, calculated from ``m``, + ``fabric_only``, ``nice_coordinates`` and ``coordinates`` as described below. + Edges should be 2-tuples of nodes that match the + requested coordinate system and topology bounds. Edges incompatible + with the requested topology are accepted by default. Nodes + present in the ``edge_list``, but absent in the ``node_list`` are + removed. data : bool, optional (default True) If True, each node has a pegasus_index attribute. The attribute is a 4-tuple Pegasus index as defined below. If the `coordinates` parameter @@ -83,6 +100,16 @@ def pegasus_graph(m, create_using=None, node_list=None, edge_list=None, data=Tru For any given :math:`0 <= t0 < 3`, the subgraph of nodes with :math:`t = t0` has the structure of `chimera(M-1, M-1, 4)` with the addition of odd couplers. Supercedes both the `fabric_only` and `coordinates` parameters. + check_node_list : bool (optional, default False) + If True, the node_list elements are checked for compatibility with + the graph topology and node labeling conventions, an error is thrown + if any node is incompatible. In other words, only node_lists that + specify subgraphs of the default (full yield) graph are permitted. + check_edge_list : bool (optional, default False) + If True, the edge_list elements are checked for compatibility with + the graph topology and node labeling conventions, an error is thrown + if any edge is incompatible. In other words, only edge_lists that + specify subgraphs of the default (full yield) graph are permitted. Returns ------- @@ -216,7 +243,7 @@ def label(u, w, k, z): max_size = m * (m - 1) * 24 # max number of nodes G can have - if edge_list is None: + if edge_list is None or check_edge_list is True: if nice_coordinates: fabric_start = 4,8 fabric_end = 8, 4 @@ -252,13 +279,22 @@ def efilter(e): return qfilter(*e[0]) and qfilter(*e[1]) for z in range(m1)) G.add_edges_from((label(*e[0]), label(*e[1])) for e in internal_couplers if efilter(e)) + if edge_list is not None: + _add_compatible_edges(G, edge_list) else: G.add_edges_from(edge_list) if node_list is not None: nodes = set(node_list) G.remove_nodes_from(set(G) - nodes) - G.add_nodes_from(nodes) # for singleton nodes + if check_node_list: + if G.number_of_nodes() != len(nodes): + raise ValueError("node_list contains nodes incompatible with " + "the specified topology and node-labeling " + "convention.") + + else: + G.add_nodes_from(nodes) # for singleton nodes if data: v = 0 diff --git a/dwave_networkx/generators/zephyr.py b/dwave_networkx/generators/zephyr.py index 823a1384..21bf564e 100644 --- a/dwave_networkx/generators/zephyr.py +++ b/dwave_networkx/generators/zephyr.py @@ -30,9 +30,18 @@ 'zephyr_sublattice_mappings', ] +def _add_compatible_edges(G, edge_list): + # Slow when edge_list is large, but clear (non-defaulted behaviour, so fine): + if edge_list is not None: + if not all([G.has_edge(*e) for e in edge_list]): + raise ValueError("edge_list contains edges incompatible with a " + "fully yielded graph of the requested topology") + if len(edge_list) < G.number_of_edges(): + G.remove_edges_from(list(G.edges)) + G.add_edges_from(edge_list) def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, - data=True, coordinates=False): + data=True, coordinates=False, check_node_list=False, check_edge_list=False): """ Creates a Zephyr graph with grid parameter ``m`` and tile parameter ``t``. @@ -47,15 +56,20 @@ def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, create_using : Graph, optional (default None) If provided, this graph is cleared of nodes and edges and filled with the new graph. Usually used to set the type of the graph. - node_list : iterable, optional (default None) - Iterable of nodes in the graph. If None, calculated from ``m``. - Note that this list is used to remove nodes, so only specified nodes - that belong to the base node set (described in the ``coordinates`` - parameter) are added. - edge_list : iterable, optional (default None) - Iterable of edges in the graph. If None, edges are generated as - described below. The nodes in each edge must be labeled according to the - ``coordinates`` parameter. + node_list : iterable (optional, default None) + Iterable of nodes in the graph. If None, calculated from (``m``, ``t``) + and ``coordinates``. The nodes should be compatible with the requested + coordinate system and topology bounds; by default integer-labeled + in :code:`range(4 * t * m * (2 * m + 1))`. Nodes incompatible with + the requested topology are accepted by default. + edge_list : iterable (optional, default None) + Iterable of edges in the graph. If None, calculated + from (``m``, ``t``) and ``coordinates`` as described below. + Edges should be 2-tuples of nodes that match the + requested coordinate system and topology bounds. Edges incompatible + with the requested topology are accepted by default. Nodes + present in the ``edge_list``, but absent in the ``node_list`` are + removed. data : bool, optional (default True) If True, adds to each node an attribute with a format that depends on the ``coordinates`` parameter: a 5-tuple ``'zephyr_index'`` if @@ -163,7 +177,7 @@ def label(u, w, k, j, z): G.graph.update(construction) - if edge_list is None: + if edge_list is None or check_edge_list is True: #external edges G.add_edges_from((label(u, w, k, j, z), label(u, w, k, j, z + 1)) for u, w, k, j, z in product( @@ -182,14 +196,22 @@ def label(u, w, k, j, z): for w, z, h, k, i, j, a, b in product( range(m), range(m), range(t), range(t), (0, 1), (0, 1), (0, 1), (0, 1) )) - + if edge_list is not None: + _add_compatible_edges(G, edge_list) else: G.add_edges_from(edge_list) if node_list is not None: nodes = set(node_list) G.remove_nodes_from(set(G) - nodes) - G.add_nodes_from(nodes) # for singleton nodes + if check_node_list: + if G.number_of_nodes() != len(nodes): + raise ValueError("node_list contains nodes incompatible with " + "the specified topology and node-labeling " + "convention.") + + else: + G.add_nodes_from(nodes) # for singleton nodes if data: if coordinates: diff --git a/tests/test_generator_pegasus.py b/tests/test_generator_pegasus.py index 9c7e75c5..0d551f39 100644 --- a/tests/test_generator_pegasus.py +++ b/tests/test_generator_pegasus.py @@ -290,6 +290,63 @@ def check_subgraph_mapping(f, g, h): self.assertEqual(covered, set(target)) + def test_edge_list(self): + m=4 + G = dnx.pegasus_graph(m) + edge_list = list(G.edges) + #Valid (default) edge_list + G = dnx.pegasus_graph(m, edge_list=edge_list, + check_edge_list=True) + + #Valid edge_list in coordinate system + edge_list = [((0,0,0,0),(0,0,1,0))] + G = dnx.pegasus_graph(m, edge_list=edge_list, + check_node_list=True, coordinates=True) + + with self.assertRaises(ValueError): + #Invalid edge_list. + edge_list = [(0,2)] #Vertical next nearest, no edge. + G = dnx.pegasus_graph(m, edge_list=edge_list, fabric_only=False, + check_edge_list=True) + + def test_node_list(self): + m=4 + G = dnx.pegasus_graph(m) + #Valid (default) node_list + node_list = list(G.nodes) + G = dnx.pegasus_graph(m, node_list=node_list, + check_node_list=True) + + with self.assertRaises(ValueError): + #invalid node_list on any shape m pegasus graph + node_list = [0,m*(m-1)*24] + G = dnx.pegasus_graph(m, node_list=node_list, fabric_only=False, + check_node_list=True) + + + #Invalid node_list (fabric_only and nice only): + node_list = [0] + with self.assertRaises(ValueError): + G = dnx.pegasus_graph(m, node_list=node_list, fabric_only=True, + check_node_list=True) + with self.assertRaises(ValueError): + node_list = [dnx.pegasus_coordinates(m).linear_to_nice(0)] + G = dnx.pegasus_graph(m, node_list=node_list, nice_coordinates=True, + check_node_list=True) + + + #Valid coordinate presentation: + node_list = [(0,0,0,0)] + G = dnx.pegasus_graph(m, node_list=node_list, fabric_only=False, + check_node_list=True, coordinates=True) + with self.assertRaises(ValueError): + #Incompatible coordinate presentation: + node_list = [0] + G = dnx.pegasus_graph(m, node_list=node_list, fabric_only=False, + check_node_list=True, coordinates=True) + + + class TestTupleFragmentation(unittest.TestCase): def test_empty_list(self): diff --git a/tests/test_generator_zephyr.py b/tests/test_generator_zephyr.py index 33aefad3..7d989a80 100644 --- a/tests/test_generator_zephyr.py +++ b/tests/test_generator_zephyr.py @@ -188,3 +188,47 @@ def check_subgraph_mapping(f, g, h): covered.update(map(f, source)) self.assertEqual(covered, set(target)) + + def test_edge_list(self): + m=2 + t=4 + G = dnx.zephyr_graph(m, t) + edge_list = list(G.edges) + #Valid (full) edge_list + G = dnx.zephyr_graph(m, t, edge_list=edge_list, + check_edge_list=True) + + #Valid edge_list in coordinate system + edge_list = [((0,0,0,0),(0,0,1,0))] + G = dnx.zephyr_graph(m, t, edge_list=edge_list, + check_node_list=True, coordinates=True) + + with self.assertRaises(ValueError): + #Invalid edge_list (0,1) is a vertical-vertical coupler. + edge_list = [(0,t),(0,1)] + G = dnx.zephyr_graph(m, t, edge_list=edge_list, + check_edge_list=True) + + def test_node_list(self): + m=4 + t=2 + G = dnx.chimera_graph(m,t) + #Valid (full) node_list + node_list = list(G.nodes) + G = dnx.zephyr_graph(m, t, node_list=node_list, + check_node_list=True) + #Valid node_list in coordinate system + node_list = [(0, 0, 0, 0, 0)] + G = dnx.zephyr_graph(m, t, node_list=node_list, + check_node_list=True, coordinates=True) + with self.assertRaises(ValueError): + #Invalid node_list + node_list = [0, 4 * t * m * (2 * m + 1)] + G = dnx.zephyr_graph(m, t, node_list=node_list, + check_node_list=True) + with self.assertRaises(ValueError): + #node is valid, but not in the requested coordinate system + node_list = [0] + G = dnx.zephyr_graph(m, t, node_list=node_list, + check_node_list=True, coordinates=True) + From c62e66a638f347ce6cd58402e87c32b74865b511 Mon Sep 17 00:00:00 2001 From: Jack Raymond <10591246+jackraymond@users.noreply.github.com> Date: Fri, 15 Jul 2022 15:47:01 -0700 Subject: [PATCH 03/15] Tidying up docstrings, tidying up unit tests --- dwave_networkx/generators/chimera.py | 9 +++-- dwave_networkx/generators/pegasus.py | 13 ++++--- dwave_networkx/generators/zephyr.py | 9 +++-- tests/test_generator_chimera.py | 53 +++++++++++++++++----------- tests/test_generator_pegasus.py | 50 +++++++++++++++----------- tests/test_generator_zephyr.py | 53 +++++++++++++++++----------- 6 files changed, 108 insertions(+), 79 deletions(-) diff --git a/dwave_networkx/generators/chimera.py b/dwave_networkx/generators/chimera.py index 1799bfb3..cf3569ce 100644 --- a/dwave_networkx/generators/chimera.py +++ b/dwave_networkx/generators/chimera.py @@ -68,12 +68,11 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis with the requested topology are accepted by default. edge_list : iterable (optional, default None) Iterable of edges in the graph. If None, calculated - from (``m``, ``n``, ``t``) and ``coordinates`` as described below. + from the ``node_list`` as described below. Edges should be 2-tuples of nodes that match the - requested coordinate system and topology bounds. Edges incompatible - with the requested topology are accepted by default. Nodes - present in the ``edge_list``, but absent in the ``node_list`` are - removed. + requested coordinate system and topology bounds. Edges are accepted by + default, provided component nodes are contained in the ``node_list``, + otherwise they are ignored. data : bool (optional, default True) If True, each node has a `chimera_index attribute`. The attribute is a 4-tuple Chimera index diff --git a/dwave_networkx/generators/pegasus.py b/dwave_networkx/generators/pegasus.py index da240d94..e1bf7e5a 100644 --- a/dwave_networkx/generators/pegasus.py +++ b/dwave_networkx/generators/pegasus.py @@ -56,19 +56,18 @@ def pegasus_graph(m, create_using=None, node_list=None, edge_list=None, data=Tru with the new graph. Usually used to set the type of the graph. node_list : iterable (optional, default None) Iterable of nodes in the graph. If None, calculated - from ``m``,``fabric_only``, ``nice_coordinates`` and + from ``m``, ``fabric_only``, ``nice_coordinates`` and ``coordinates`` as described below. The nodes should be compatible with the requested coordinate system and topology bounds; by default integer-labeled in :code:`range(m * (m-1) * 24)`. Nodes incompatible with the requested topology are accepted by default. edge_list : iterable (optional, default None) - Iterable of edges in the graph. If None, calculated from ``m``, - ``fabric_only``, ``nice_coordinates`` and ``coordinates`` as described below. + Iterable of edges in the graph. If None, calculated from the + ``node_list`` as described below. Edges should be 2-tuples of nodes that match the - requested coordinate system and topology bounds. Edges incompatible - with the requested topology are accepted by default. Nodes - present in the ``edge_list``, but absent in the ``node_list`` are - removed. + requested coordinate system and topology bounds. Edges are accepted by + default, provided component nodes are contained in the ``node_list``, + otherwise they are ignored. data : bool, optional (default True) If True, each node has a pegasus_index attribute. The attribute is a 4-tuple Pegasus index as defined below. If the `coordinates` parameter diff --git a/dwave_networkx/generators/zephyr.py b/dwave_networkx/generators/zephyr.py index 21bf564e..df5a2417 100644 --- a/dwave_networkx/generators/zephyr.py +++ b/dwave_networkx/generators/zephyr.py @@ -64,12 +64,11 @@ def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, the requested topology are accepted by default. edge_list : iterable (optional, default None) Iterable of edges in the graph. If None, calculated - from (``m``, ``t``) and ``coordinates`` as described below. + from the ``node_list`` as described below. Edges should be 2-tuples of nodes that match the - requested coordinate system and topology bounds. Edges incompatible - with the requested topology are accepted by default. Nodes - present in the ``edge_list``, but absent in the ``node_list`` are - removed. + requested coordinate system and topology bounds. Edges are accepted by + default, provided component nodes are contained in the ``node_list``, + otherwise they are ignored. data : bool, optional (default True) If True, adds to each node an attribute with a format that depends on the ``coordinates`` parameter: a 5-tuple ``'zephyr_index'`` if diff --git a/tests/test_generator_chimera.py b/tests/test_generator_chimera.py index dcb919f3..32e80b9b 100644 --- a/tests/test_generator_chimera.py +++ b/tests/test_generator_chimera.py @@ -283,27 +283,6 @@ def check_subgraph_mapping(f, g, h): self.assertEqual(covered, set(target)) - def test_edge_list(self): - m=2 - n=3 - t=4 - G = dnx.chimera_graph(m, n, t) - edge_list = list(G.edges) - #Valid (full) edge_list - G = dnx.chimera_graph(m, n, t, edge_list=edge_list, - check_edge_list=True) - - #Valid edge_list in coordinate system - edge_list = [((0,0,0,0),(0,0,1,0))] - G = dnx.chimera_graph(m, n, t, edge_list=edge_list, - check_node_list=True, coordinates=True) - - with self.assertRaises(ValueError): - #Invalid edge_list (0,1) is a vertical-vertical coupler. - edge_list = [(0,t),(0,1)] - G = dnx.chimera_graph(m, n, t, edge_list=edge_list, - check_edge_list=True) - def test_node_list(self): m=4 n=3 @@ -313,10 +292,12 @@ def test_node_list(self): node_list = list(G.nodes) G = dnx.chimera_graph(m, n, t, node_list=node_list, check_node_list=True) + self.assertEqual(G.number_of_nodes(), len(node_list)) #Valid node_list in coordinate system node_list = [(0,0,0,0)] G = dnx.chimera_graph(m, n, t, node_list=node_list, check_node_list=True, coordinates=True) + self.assertEqual(G.number_of_nodes(), len(node_list)) with self.assertRaises(ValueError): #Invalid node_list node_list = [0,m*n*t*2] @@ -328,3 +309,33 @@ def test_node_list(self): G = dnx.chimera_graph(m, n, t, node_list=node_list, check_node_list=True, coordinates=True) + + def test_edge_list(self): + m=2 + n=3 + t=4 + G = dnx.chimera_graph(m, n, t) + edge_list = list(G.edges) + #Valid (full) edge_list + G = dnx.chimera_graph(m, n, t, edge_list=edge_list, + check_edge_list=True) + self.assertEqual(G.number_of_edges(),len(edge_list)) + #Valid edge_list in coordinate system + edge_list = [((0,0,0,0),(0,0,1,0))] + G = dnx.chimera_graph(m, n, t, edge_list=edge_list, + check_edge_list=True, coordinates=True) + self.assertEqual(G.number_of_edges(),len(edge_list)) + + #Valid edge, but absent from node_list, hence dropped: + edge_list = [(0,t)] + node_list = list(range(t)) + G = dnx.chimera_graph(m, n, t, edge_list=edge_list, node_list = node_list, + check_edge_list=True) + self.assertEqual(G.number_of_edges(),0) + + with self.assertRaises(ValueError): + #Invalid edge_list (0,1) is a vertical-vertical coupler. + edge_list = [(0,t),(0,1)] + G = dnx.chimera_graph(m, n, t, edge_list=edge_list, + check_edge_list=True) + diff --git a/tests/test_generator_pegasus.py b/tests/test_generator_pegasus.py index 0d551f39..67820a4d 100644 --- a/tests/test_generator_pegasus.py +++ b/tests/test_generator_pegasus.py @@ -289,26 +289,6 @@ def check_subgraph_mapping(f, g, h): covered.update(map(f, source)) self.assertEqual(covered, set(target)) - - def test_edge_list(self): - m=4 - G = dnx.pegasus_graph(m) - edge_list = list(G.edges) - #Valid (default) edge_list - G = dnx.pegasus_graph(m, edge_list=edge_list, - check_edge_list=True) - - #Valid edge_list in coordinate system - edge_list = [((0,0,0,0),(0,0,1,0))] - G = dnx.pegasus_graph(m, edge_list=edge_list, - check_node_list=True, coordinates=True) - - with self.assertRaises(ValueError): - #Invalid edge_list. - edge_list = [(0,2)] #Vertical next nearest, no edge. - G = dnx.pegasus_graph(m, edge_list=edge_list, fabric_only=False, - check_edge_list=True) - def test_node_list(self): m=4 G = dnx.pegasus_graph(m) @@ -316,6 +296,7 @@ def test_node_list(self): node_list = list(G.nodes) G = dnx.pegasus_graph(m, node_list=node_list, check_node_list=True) + self.assertEqual(G.number_of_nodes(), len(node_list)) with self.assertRaises(ValueError): #invalid node_list on any shape m pegasus graph @@ -339,13 +320,40 @@ def test_node_list(self): node_list = [(0,0,0,0)] G = dnx.pegasus_graph(m, node_list=node_list, fabric_only=False, check_node_list=True, coordinates=True) + self.assertEqual(G.number_of_nodes(), len(node_list)) with self.assertRaises(ValueError): #Incompatible coordinate presentation: node_list = [0] G = dnx.pegasus_graph(m, node_list=node_list, fabric_only=False, check_node_list=True, coordinates=True) - + def test_edge_list(self): + m=4 + G = dnx.pegasus_graph(m) + edge_list = list(G.edges) + #Valid (default) edge_list + G = dnx.pegasus_graph(m, edge_list=edge_list, + check_edge_list=True) + self.assertEqual(G.number_of_edges(),len(edge_list)) + #Valid edge_list in coordinate system + edge_list = [((0, 0, 2, 0), (0, 0, 2, 1))] + G = dnx.pegasus_graph(m, edge_list=edge_list, + check_edge_list=True, coordinates=True) + self.assertEqual(G.number_of_edges(),len(edge_list)) + + #Valid edge, but absent from node_list, hence dropped: + G = dnx.pegasus_graph(m, fabric_only=False) + edge_list = [(0,1)] + node_list = [0,2] + G = dnx.pegasus_graph(m, edge_list=edge_list, node_list = node_list, + check_edge_list=True,fabric_only=False) + self.assertEqual(G.number_of_edges(),0) + + with self.assertRaises(ValueError): + #Invalid edge_list. + edge_list = [(0,2)] #Vertical next nearest, no edge. + G = dnx.pegasus_graph(m, edge_list=edge_list, fabric_only=False, + check_edge_list=True) class TestTupleFragmentation(unittest.TestCase): diff --git a/tests/test_generator_zephyr.py b/tests/test_generator_zephyr.py index 7d989a80..00fce062 100644 --- a/tests/test_generator_zephyr.py +++ b/tests/test_generator_zephyr.py @@ -189,26 +189,6 @@ def check_subgraph_mapping(f, g, h): self.assertEqual(covered, set(target)) - def test_edge_list(self): - m=2 - t=4 - G = dnx.zephyr_graph(m, t) - edge_list = list(G.edges) - #Valid (full) edge_list - G = dnx.zephyr_graph(m, t, edge_list=edge_list, - check_edge_list=True) - - #Valid edge_list in coordinate system - edge_list = [((0,0,0,0),(0,0,1,0))] - G = dnx.zephyr_graph(m, t, edge_list=edge_list, - check_node_list=True, coordinates=True) - - with self.assertRaises(ValueError): - #Invalid edge_list (0,1) is a vertical-vertical coupler. - edge_list = [(0,t),(0,1)] - G = dnx.zephyr_graph(m, t, edge_list=edge_list, - check_edge_list=True) - def test_node_list(self): m=4 t=2 @@ -217,10 +197,12 @@ def test_node_list(self): node_list = list(G.nodes) G = dnx.zephyr_graph(m, t, node_list=node_list, check_node_list=True) + self.assertEqual(G.number_of_nodes(), len(node_list)) #Valid node_list in coordinate system node_list = [(0, 0, 0, 0, 0)] G = dnx.zephyr_graph(m, t, node_list=node_list, check_node_list=True, coordinates=True) + self.assertEqual(G.number_of_nodes(), len(node_list)) with self.assertRaises(ValueError): #Invalid node_list node_list = [0, 4 * t * m * (2 * m + 1)] @@ -232,3 +214,34 @@ def test_node_list(self): G = dnx.zephyr_graph(m, t, node_list=node_list, check_node_list=True, coordinates=True) + + def test_edge_list(self): + m=2 + t=4 + G = dnx.zephyr_graph(m, t) + edge_list = list(G.edges) + #Valid (full) edge_list + G = dnx.zephyr_graph(m, t, edge_list=edge_list, + check_edge_list=True) + self.assertEqual(G.number_of_edges(),len(edge_list)) + + #Valid edge_list in coordinate system + edge_list = [((0, 0, 0, 0, 0), (0, 0, 0, 0, 1))] + G = dnx.zephyr_graph(m, t, edge_list=edge_list, + check_edge_list=True, coordinates=True) + + self.assertEqual(G.number_of_edges(),len(edge_list)) + + #Valid edge, but absent from node_list, hence dropped: + edge_list = [(0,1)] + node_list = [0,2] + G = dnx.zephyr_graph(m, t, edge_list=edge_list, node_list = node_list, + check_edge_list=True) + self.assertEqual(G.number_of_edges(), 0) + + with self.assertRaises(ValueError): + #Invalid edge_list (0,1) is a vertical-vertical coupler. + edge_list = [(0, t), (0, 1)] + G = dnx.zephyr_graph(m, t, edge_list=edge_list, + check_edge_list=True) + From 9c4efaa167c469aa4bc38a93e80d13fd0551ea22 Mon Sep 17 00:00:00 2001 From: Jack Raymond <10591246+jackraymond@users.noreply.github.com> Date: Tue, 26 Jul 2022 12:21:58 -0700 Subject: [PATCH 04/15] Added corrections related to kboothby review --- dwave_networkx/generators/chimera.py | 24 ++++++---------- dwave_networkx/generators/common.py | 13 +++++++++ dwave_networkx/generators/pegasus.py | 26 ++++++----------- dwave_networkx/generators/zephyr.py | 29 +++++++++++-------- tests/test_generator_chimera.py | 34 +++++++++++++++------- tests/test_generator_pegasus.py | 43 +++++++++++++++++----------- tests/test_generator_zephyr.py | 35 +++++++++++++++------- 7 files changed, 122 insertions(+), 82 deletions(-) create mode 100644 dwave_networkx/generators/common.py diff --git a/dwave_networkx/generators/chimera.py b/dwave_networkx/generators/chimera.py index cf3569ce..f2be4cee 100644 --- a/dwave_networkx/generators/chimera.py +++ b/dwave_networkx/generators/chimera.py @@ -26,6 +26,8 @@ from itertools import product +from .common import _add_compatible_edges + __all__ = ['chimera_graph', 'chimera_coordinates', 'find_chimera_indices', @@ -35,16 +37,6 @@ ] -def _add_compatible_edges(G, edge_list): - # Slow when edge_list is large, but clear (non-defaulted behaviour, so fine): - if edge_list is not None: - if not all([G.has_edge(*e) for e in edge_list]): - raise ValueError("edge_list contains edges incompatible with a " - "fully yielded graph of the requested topology") - if len(edge_list) < G.number_of_edges(): - G.remove_edges_from(list(G.edges)) - G.add_edges_from(edge_list) - def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_list=None, data=True, coordinates=False, check_node_list=False, check_edge_list=False): """Creates a Chimera lattice of size (m, n, t). @@ -84,13 +76,15 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis check_node_list : bool (optional, default False) If True, the node_list elements are checked for compatibility with the graph topology and node labeling conventions, an error is thrown - if any node is incompatible. In other words, only node_lists that - specify subgraphs of the default (full yield) graph are permitted. + if any node is incompatible or duplicates exist. + In other words, only node_lists that specify subgraphs of the default + (full yield) graph are permitted. check_edge_list : bool (optional, default False) If True, the edge_list elements are checked for compatibility with the graph topology and node labeling conventions, an error is thrown - if any edge is incompatible. In other words, only edge_lists that - specify subgraphs of the default (full yield) graph are permitted. + if any edge is incompatible or duplicates exist. + In other words, only edge_lists that specify subgraphs of the default + (full yield) graph are permitted. Returns ------- @@ -216,7 +210,7 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis nodes = set(node_list) G.remove_nodes_from(set(G) - nodes) if check_node_list: - if G.number_of_nodes() != len(nodes): + if G.number_of_nodes() != len(node_list): raise ValueError("node_list contains nodes incompatible with " "the specified topology and node-labeling " "convention.") diff --git a/dwave_networkx/generators/common.py b/dwave_networkx/generators/common.py new file mode 100644 index 00000000..1e9209f2 --- /dev/null +++ b/dwave_networkx/generators/common.py @@ -0,0 +1,13 @@ + +def _add_compatible_edges(G, edge_list): + # Check edge_list defines a subgraph of G and create subgraph. + # Slow when edge_list is large, but clear (non-defaulted behaviour, so fine): + if edge_list is not None: + if not all(G.has_edge(*e) for e in edge_list): + raise ValueError("edge_list contains edges incompatible with a " + "fully yielded graph of the requested topology") + # Hard to check edge_list consistency owing to directedness, etc. Brute force + G.remove_edges_from(list(G.edges)) + G.add_edges_from(edge_list) + if G.number_of_edges() < len(edge_list): + raise ValueError('edge_list contains duplicates.') diff --git a/dwave_networkx/generators/pegasus.py b/dwave_networkx/generators/pegasus.py index e1bf7e5a..a6932aca 100644 --- a/dwave_networkx/generators/pegasus.py +++ b/dwave_networkx/generators/pegasus.py @@ -24,23 +24,13 @@ from itertools import product from .chimera import _chimera_coordinates_cache +from .common import _add_compatible_edges __all__ = ['pegasus_graph', 'pegasus_coordinates', 'pegasus_sublattice_mappings', ] - -def _add_compatible_edges(G, edge_list): - # Slow when edge_list is large, but clear (non-defaulted behaviour, so fine): - if edge_list is not None: - if not all([G.has_edge(*e) for e in edge_list]): - raise ValueError("edge_list contains edges incompatible with a " - "fully yielded graph of the requested topology") - if len(edge_list) < G.number_of_edges(): - G.remove_edges_from(list(G.edges)) - G.add_edges_from(edge_list) - def pegasus_graph(m, create_using=None, node_list=None, edge_list=None, data=True, offset_lists=None, offsets_index=None, coordinates=False, fabric_only=True, nice_coordinates=False, check_node_list=False, check_edge_list=False): @@ -102,13 +92,15 @@ def pegasus_graph(m, create_using=None, node_list=None, edge_list=None, data=Tru check_node_list : bool (optional, default False) If True, the node_list elements are checked for compatibility with the graph topology and node labeling conventions, an error is thrown - if any node is incompatible. In other words, only node_lists that - specify subgraphs of the default (full yield) graph are permitted. + if any node is incompatible or duplicates exist. + In other words, only node_lists that specify subgraphs of the default + (full yield) graph are permitted. check_edge_list : bool (optional, default False) If True, the edge_list elements are checked for compatibility with the graph topology and node labeling conventions, an error is thrown - if any edge is incompatible. In other words, only edge_lists that - specify subgraphs of the default (full yield) graph are permitted. + if any edge is incompatible or duplicates exist. + In other words, only edge_lists that specify subgraphs of the default + (full yield) graph are permitted. Returns ------- @@ -287,10 +279,10 @@ def efilter(e): return qfilter(*e[0]) and qfilter(*e[1]) nodes = set(node_list) G.remove_nodes_from(set(G) - nodes) if check_node_list: - if G.number_of_nodes() != len(nodes): + if G.number_of_nodes() != len(node_list): raise ValueError("node_list contains nodes incompatible with " "the specified topology and node-labeling " - "convention.") + "convention, or duplicates") else: G.add_nodes_from(nodes) # for singleton nodes diff --git a/dwave_networkx/generators/zephyr.py b/dwave_networkx/generators/zephyr.py index df5a2417..fd7f32aa 100644 --- a/dwave_networkx/generators/zephyr.py +++ b/dwave_networkx/generators/zephyr.py @@ -25,21 +25,13 @@ from .chimera import _chimera_coordinates_cache +from .common import _add_compatible_edges + __all__ = ['zephyr_graph', 'zephyr_coordinates', 'zephyr_sublattice_mappings', ] -def _add_compatible_edges(G, edge_list): - # Slow when edge_list is large, but clear (non-defaulted behaviour, so fine): - if edge_list is not None: - if not all([G.has_edge(*e) for e in edge_list]): - raise ValueError("edge_list contains edges incompatible with a " - "fully yielded graph of the requested topology") - if len(edge_list) < G.number_of_edges(): - G.remove_edges_from(list(G.edges)) - G.add_edges_from(edge_list) - def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, data=True, coordinates=False, check_node_list=False, check_edge_list=False): """ @@ -76,6 +68,18 @@ def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, is True. coordinates : bool, optional (default False) If True, node labels are 5-tuple Zephyr indices. + check_node_list : bool (optional, default False) + If True, the node_list elements are checked for compatibility with + the graph topology and node labeling conventions, an error is thrown + if any node is incompatible or duplicates exist. + In other words, only node_lists that specify subgraphs of the default + (full yield) graph are permitted. + check_edge_list : bool (optional, default False) + If True, the edge_list elements are checked for compatibility with + the graph topology and node labeling conventions, an error is thrown + if any edge is incompatible or duplicates exist. + In other words, only edge_lists that specify subgraphs of the default + (full yield) graph are permitted. Returns ------- @@ -204,10 +208,11 @@ def label(u, w, k, j, z): nodes = set(node_list) G.remove_nodes_from(set(G) - nodes) if check_node_list: - if G.number_of_nodes() != len(nodes): + if G.number_of_nodes() != len(node_list): raise ValueError("node_list contains nodes incompatible with " "the specified topology and node-labeling " - "convention.") + "convention, or duplicates") + else: G.add_nodes_from(nodes) # for singleton nodes diff --git a/tests/test_generator_chimera.py b/tests/test_generator_chimera.py index 32e80b9b..755cba3f 100644 --- a/tests/test_generator_chimera.py +++ b/tests/test_generator_chimera.py @@ -284,9 +284,10 @@ def check_subgraph_mapping(f, g, h): def test_node_list(self): - m=4 - n=3 - t=2 + m = 4 + n = 3 + t = 2 + N = m*n*t*2 G = dnx.chimera_graph(m,n,t) #Valid (full) node_list node_list = list(G.nodes) @@ -300,9 +301,15 @@ def test_node_list(self): self.assertEqual(G.number_of_nodes(), len(node_list)) with self.assertRaises(ValueError): #Invalid node_list - node_list = [0,m*n*t*2] + node_list = [0, N] G = dnx.chimera_graph(m, n, t, node_list=node_list, check_node_list=True) + with self.assertRaises(ValueError): + # Invalid node_list due to duplicates + node_list = [0, 0] + G = dnx.chimera_graph(m, node_list=node_list, + check_node_list=True) + with self.assertRaises(ValueError): #node is valid, but not in the requested coordinate system node_list = [0] @@ -311,22 +318,22 @@ def test_node_list(self): def test_edge_list(self): - m=2 - n=3 - t=4 + m = 2 + n = 3 + t = 4 G = dnx.chimera_graph(m, n, t) edge_list = list(G.edges) - #Valid (full) edge_list + # Valid (full) edge_list G = dnx.chimera_graph(m, n, t, edge_list=edge_list, check_edge_list=True) self.assertEqual(G.number_of_edges(),len(edge_list)) - #Valid edge_list in coordinate system + # Valid edge_list in coordinate system edge_list = [((0,0,0,0),(0,0,1,0))] G = dnx.chimera_graph(m, n, t, edge_list=edge_list, check_edge_list=True, coordinates=True) self.assertEqual(G.number_of_edges(),len(edge_list)) - #Valid edge, but absent from node_list, hence dropped: + # Valid edge, but absent from node_list, hence dropped: edge_list = [(0,t)] node_list = list(range(t)) G = dnx.chimera_graph(m, n, t, edge_list=edge_list, node_list = node_list, @@ -334,8 +341,13 @@ def test_edge_list(self): self.assertEqual(G.number_of_edges(),0) with self.assertRaises(ValueError): - #Invalid edge_list (0,1) is a vertical-vertical coupler. + # Invalid edge_list (0,1) is a vertical-vertical coupler. edge_list = [(0,t),(0,1)] G = dnx.chimera_graph(m, n, t, edge_list=edge_list, check_edge_list=True) + with self.assertRaises(ValueError): + # Edge list has duplicates + edge_list = [(0, t), (0, t)] + G = dnx.chimera_graph(m, edge_list=edge_list, + check_edge_list=True) diff --git a/tests/test_generator_pegasus.py b/tests/test_generator_pegasus.py index 67820a4d..66ba741f 100644 --- a/tests/test_generator_pegasus.py +++ b/tests/test_generator_pegasus.py @@ -290,71 +290,82 @@ def check_subgraph_mapping(f, g, h): self.assertEqual(covered, set(target)) def test_node_list(self): - m=4 + m = 4 G = dnx.pegasus_graph(m) - #Valid (default) node_list + # Valid (default) node_list node_list = list(G.nodes) G = dnx.pegasus_graph(m, node_list=node_list, check_node_list=True) self.assertEqual(G.number_of_nodes(), len(node_list)) with self.assertRaises(ValueError): - #invalid node_list on any shape m pegasus graph + # Invalid node_list on any shape m pegasus graph node_list = [0,m*(m-1)*24] G = dnx.pegasus_graph(m, node_list=node_list, fabric_only=False, check_node_list=True) - + with self.assertRaises(ValueError): + # Invalid node_list due to duplicates + node_list = [0, 0] + G = dnx.pegasus_graph(m, node_list=node_list, fabric_only=False, + check_node_list=True) - #Invalid node_list (fabric_only and nice only): - node_list = [0] with self.assertRaises(ValueError): + # Invalid node_list (fabric_only) + node_list = [0] G = dnx.pegasus_graph(m, node_list=node_list, fabric_only=True, check_node_list=True) with self.assertRaises(ValueError): + # Invalid node_list (nice_coordinates) node_list = [dnx.pegasus_coordinates(m).linear_to_nice(0)] G = dnx.pegasus_graph(m, node_list=node_list, nice_coordinates=True, check_node_list=True) - #Valid coordinate presentation: + # Valid coordinate presentation: node_list = [(0,0,0,0)] G = dnx.pegasus_graph(m, node_list=node_list, fabric_only=False, check_node_list=True, coordinates=True) self.assertEqual(G.number_of_nodes(), len(node_list)) with self.assertRaises(ValueError): - #Incompatible coordinate presentation: + # Incompatible coordinate presentation: node_list = [0] G = dnx.pegasus_graph(m, node_list=node_list, fabric_only=False, check_node_list=True, coordinates=True) def test_edge_list(self): - m=4 + m = 4 G = dnx.pegasus_graph(m) edge_list = list(G.edges) - #Valid (default) edge_list + # Valid (default) edge_list G = dnx.pegasus_graph(m, edge_list=edge_list, check_edge_list=True) self.assertEqual(G.number_of_edges(),len(edge_list)) - #Valid edge_list in coordinate system + # Valid edge_list in coordinate system edge_list = [((0, 0, 2, 0), (0, 0, 2, 1))] G = dnx.pegasus_graph(m, edge_list=edge_list, check_edge_list=True, coordinates=True) - self.assertEqual(G.number_of_edges(),len(edge_list)) + self.assertEqual(G.number_of_edges(), len(edge_list)) - #Valid edge, but absent from node_list, hence dropped: + # Valid edge, but absent from node_list, hence dropped: G = dnx.pegasus_graph(m, fabric_only=False) edge_list = [(0,1)] node_list = [0,2] G = dnx.pegasus_graph(m, edge_list=edge_list, node_list = node_list, - check_edge_list=True,fabric_only=False) + fabric_only=False, check_edge_list=True) self.assertEqual(G.number_of_edges(),0) with self.assertRaises(ValueError): - #Invalid edge_list. + # Invalid edge_list. edge_list = [(0,2)] #Vertical next nearest, no edge. G = dnx.pegasus_graph(m, edge_list=edge_list, fabric_only=False, check_edge_list=True) - + + with self.assertRaises(ValueError): + # Edge list has duplicates + edge_list = [(0, 1), (0, 1)] + G = dnx.pegasus_graph(m, edge_list=edge_list, fabric_only=False, + check_edge_list=True) + class TestTupleFragmentation(unittest.TestCase): def test_empty_list(self): diff --git a/tests/test_generator_zephyr.py b/tests/test_generator_zephyr.py index 00fce062..b4c66844 100644 --- a/tests/test_generator_zephyr.py +++ b/tests/test_generator_zephyr.py @@ -192,24 +192,31 @@ def check_subgraph_mapping(f, g, h): def test_node_list(self): m=4 t=2 + N = 4 * t * m * (2 * m + 1) G = dnx.chimera_graph(m,t) - #Valid (full) node_list + # Valid (full) node_list node_list = list(G.nodes) G = dnx.zephyr_graph(m, t, node_list=node_list, check_node_list=True) self.assertEqual(G.number_of_nodes(), len(node_list)) - #Valid node_list in coordinate system + # Valid node_list in coordinate system node_list = [(0, 0, 0, 0, 0)] G = dnx.zephyr_graph(m, t, node_list=node_list, check_node_list=True, coordinates=True) self.assertEqual(G.number_of_nodes(), len(node_list)) with self.assertRaises(ValueError): - #Invalid node_list - node_list = [0, 4 * t * m * (2 * m + 1)] + # Invalid node + node_list = [0, N] G = dnx.zephyr_graph(m, t, node_list=node_list, check_node_list=True) with self.assertRaises(ValueError): - #node is valid, but not in the requested coordinate system + # Duplicates + node_list = [0, 0] + G = dnx.zephyr_graph(m, node_list=node_list, + check_node_list=True) + + with self.assertRaises(ValueError): + # Not in the requested coordinate system node_list = [0] G = dnx.zephyr_graph(m, t, node_list=node_list, check_node_list=True, coordinates=True) @@ -218,21 +225,22 @@ def test_node_list(self): def test_edge_list(self): m=2 t=4 + N = 4 * t * m * (2 * m + 1) G = dnx.zephyr_graph(m, t) edge_list = list(G.edges) - #Valid (full) edge_list + # Valid (full) edge_list G = dnx.zephyr_graph(m, t, edge_list=edge_list, check_edge_list=True) self.assertEqual(G.number_of_edges(),len(edge_list)) - #Valid edge_list in coordinate system + # Valid edge_list in coordinate system edge_list = [((0, 0, 0, 0, 0), (0, 0, 0, 0, 1))] G = dnx.zephyr_graph(m, t, edge_list=edge_list, check_edge_list=True, coordinates=True) self.assertEqual(G.number_of_edges(),len(edge_list)) - #Valid edge, but absent from node_list, hence dropped: + # Valid edge, but absent from node_list, hence dropped: edge_list = [(0,1)] node_list = [0,2] G = dnx.zephyr_graph(m, t, edge_list=edge_list, node_list = node_list, @@ -240,8 +248,13 @@ def test_edge_list(self): self.assertEqual(G.number_of_edges(), 0) with self.assertRaises(ValueError): - #Invalid edge_list (0,1) is a vertical-vertical coupler. - edge_list = [(0, t), (0, 1)] + # Invalid edge_list (0,N-1). + edge_list = [(0, N-1), (0, 1)] + G = dnx.zephyr_graph(m, t, edge_list=edge_list, + check_edge_list=True) + + with self.assertRaises(ValueError): + # Edge list has duplicates + edge_list = [(0, 1), (0, 1)] G = dnx.zephyr_graph(m, t, edge_list=edge_list, check_edge_list=True) - From 0c21f1f5c47d38cc6a5e21bb1849ba4cd6658935 Mon Sep 17 00:00:00 2001 From: Jack Raymond <10591246+jackraymond@users.noreply.github.com> Date: Wed, 10 Aug 2022 11:59:15 -0700 Subject: [PATCH 05/15] docstring edits in response to Joels comments --- .../algorithms/elimination_ordering.py | 2 +- dwave_networkx/generators/chimera.py | 52 +++++++------- dwave_networkx/generators/pegasus.py | 71 ++++++++++--------- dwave_networkx/generators/zephyr.py | 45 ++++++------ 4 files changed, 86 insertions(+), 84 deletions(-) diff --git a/dwave_networkx/algorithms/elimination_ordering.py b/dwave_networkx/algorithms/elimination_ordering.py index 58b57cc7..625758ba 100644 --- a/dwave_networkx/algorithms/elimination_ordering.py +++ b/dwave_networkx/algorithms/elimination_ordering.py @@ -462,7 +462,7 @@ def elimination_order_width(G, order): def treewidth_branch_and_bound(G, elimination_order=None, treewidth_upperbound=None): """Computes the treewidth of graph G and a corresponding perfect elimination ordering. - Alogorithm based on [GD]_. + Algorithm based on [GD]_. Parameters ---------- diff --git a/dwave_networkx/generators/chimera.py b/dwave_networkx/generators/chimera.py index f2be4cee..17e7fced 100644 --- a/dwave_networkx/generators/chimera.py +++ b/dwave_networkx/generators/chimera.py @@ -53,38 +53,38 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis If provided, this graph is cleared of nodes and edges and filled with the new graph. Usually used to set the type of the graph. node_list : iterable (optional, default None) - Iterable of nodes in the graph. If None, calculated from (``m``, ``n``, ``t``) - and ``coordinates``. The nodes should be compatible with the requested - coordinate system and topology bounds; by default integer-labeled - in :code:`range(m * n * t * 2)`. Nodes incompatible - with the requested topology are accepted by default. + Iterable of nodes in the graph. The nodes should typically be + compatible with the requested lattice shape parameters and coordinate + system, incompatible nodes are accepted unless you set :code:`check_node_list=True`. + If not specified, calculated from (``m``, ``n``, ``t``) and + ``coordinates`` per the topology description below; all :math:`2 t m n` + nodes are included. edge_list : iterable (optional, default None) - Iterable of edges in the graph. If None, calculated - from the ``node_list`` as described below. - Edges should be 2-tuples of nodes that match the - requested coordinate system and topology bounds. Edges are accepted by - default, provided component nodes are contained in the ``node_list``, - otherwise they are ignored. - data : bool (optional, default True) - If True, each node has a - `chimera_index attribute`. The attribute is a 4-tuple Chimera index - as defined below. - coordinates : bool (optional, default False) - If True, node labels are 4-tuples, equivalent to the chimera_index + Iterable of edges in the graph. Edges must be 2-tuples of the nodes + specified in node_list, or calculated from (``m``, ``n``, ``t``) and + ``coordinates`` per the topology description below; incompatible edges + are ignored unless you set :code:`check_edge_list=True`. If not + specified, all edges compatible with the ``node_list`` and topology + description are included. + data : bool (optional, default :code:`True`) + If :code:`True`, each node has a `chimera_index attribute`. The + attribute is a 4-tuple Chimera index as defined below. + coordinates : bool (optional, default :code:`False`) + If :code:`True`, node labels are 4-tuples, equivalent to the chimera_index attribute as below. In this case, the `data` parameter controls the existence of a `linear_index attribute`, which is an int. - check_node_list : bool (optional, default False) - If True, the node_list elements are checked for compatibility with - the graph topology and node labeling conventions, an error is thrown + check_node_list : bool (optional, default :code:`False`) + If :code:`True`, the ``node_list`` elements are checked for compatibility with + the graph topology and node labeling conventions, and an error is thrown if any node is incompatible or duplicates exist. - In other words, only node_lists that specify subgraphs of the default - (full yield) graph are permitted. - check_edge_list : bool (optional, default False) - If True, the edge_list elements are checked for compatibility with + In other words, the ``node_list`` must specify a subgraph of the + full-yield graph described below. + check_edge_list : bool (optional, default :code:`False`) + If :code:`True`, the edge_list elements are checked for compatibility with the graph topology and node labeling conventions, an error is thrown if any edge is incompatible or duplicates exist. - In other words, only edge_lists that specify subgraphs of the default - (full yield) graph are permitted. + In other words, the ``edge_list`` must specify a subgraph of the + full-yield graph described below. Returns ------- diff --git a/dwave_networkx/generators/pegasus.py b/dwave_networkx/generators/pegasus.py index a6932aca..48241f20 100644 --- a/dwave_networkx/generators/pegasus.py +++ b/dwave_networkx/generators/pegasus.py @@ -45,26 +45,27 @@ def pegasus_graph(m, create_using=None, node_list=None, edge_list=None, data=Tru If provided, this graph is cleared of nodes and edges and filled with the new graph. Usually used to set the type of the graph. node_list : iterable (optional, default None) - Iterable of nodes in the graph. If None, calculated - from ``m``, ``fabric_only``, ``nice_coordinates`` and - ``coordinates`` as described below. The nodes should be compatible - with the requested coordinate system and topology bounds; by - default integer-labeled in :code:`range(m * (m-1) * 24)`. Nodes - incompatible with the requested topology are accepted by default. + Iterable of nodes in the graph. The nodes should typically be + compatible with the requested lattice shape parameters and coordinate + system, incompatible nodes are accepted unless you set :code:`check_node_list=True`. + If not specified, calculated from ``m``, ``fabric_only``, + ``nice_coordinates``, ``offset_lists`` and ``offset_index`` and + ``coordinates`` per the topology description below. edge_list : iterable (optional, default None) - Iterable of edges in the graph. If None, calculated from the - ``node_list`` as described below. - Edges should be 2-tuples of nodes that match the - requested coordinate system and topology bounds. Edges are accepted by - default, provided component nodes are contained in the ``node_list``, - otherwise they are ignored. - data : bool, optional (default True) - If True, each node has a pegasus_index attribute. The attribute - is a 4-tuple Pegasus index as defined below. If the `coordinates` parameter - is True, a linear_index, which is an integer, is used. - coordinates : bool, optional (default False) - If True, node labels are 4-tuple Pegasus indices. Ignored if the - `nice_coordinates` parameter is True. + Iterable of edges in the graph. Edges must be 2-tuples of the nodes + specified in ``node_list``, or calculated from ``m``, ``fabric_only``, + ``nice_coordinates``, ``offset_lists`` and ``offset_index`` and + ``coordinates`` per the topology description below; incompatible edges + are ignored unless you set :code:`check_edge_list=True`. If not + specified, all edges compatible with the ``node_list`` and topology + description are included. + data : bool, optional (default :code:`True`) + If :code:`True`, each node has a pegasus_index attribute. The attribute + is a 4-tuple Pegasus index as defined below. If the `coordinates` + parameter is :code:`True`, a linear_index, which is an integer, is used. + coordinates : bool, optional (default :code:`False`) + If :code:`True`, node labels are 4-tuple Pegasus indices. Ignored if the + `nice_coordinates` parameter is :code:`True`. offset_lists : pair of lists, optional (default None) Directly controls the offsets. Each list in the pair must have length 12 and contain even ints. If `offset_lists` is not None, the `offsets_index` @@ -74,13 +75,13 @@ def pegasus_graph(m, create_using=None, node_list=None, edge_list=None, data=Tru set of topological parameters. If both the `offsets_index` and `offset_lists` parameters are None, the `offsets_index` parameters is set to zero. At least one of these two parameters must be None. - fabric_only: bool, optional (default True) + fabric_only: bool, optional (default :code:`True`) The Pegasus graph, by definition, has some disconnected - components. If True, the generator only constructs nodes from the - largest component. If False, the full disconnected graph is + components. If :code:`True`, the generator only constructs nodes from the + largest component. If :code:`False`, the full disconnected graph is constructed. Ignored if the `edge_lists` parameter is not None or - `nice_coordinates` is True - nice_coordinates: bool, optional (default False) + `nice_coordinates` is :code:`True` + nice_coordinates: bool, optional (default :code:`False`) If the `offsets_index` parameter is 0, the graph uses a "nicer" coordinate system, more compatible with Chimera addressing. These coordinates are 5-tuples taking the form :math:`(t, y, x, u, k)` where @@ -89,14 +90,14 @@ def pegasus_graph(m, create_using=None, node_list=None, edge_list=None, data=Tru For any given :math:`0 <= t0 < 3`, the subgraph of nodes with :math:`t = t0` has the structure of `chimera(M-1, M-1, 4)` with the addition of odd couplers. Supercedes both the `fabric_only` and `coordinates` parameters. - check_node_list : bool (optional, default False) - If True, the node_list elements are checked for compatibility with + check_node_list : bool (optional, default :code:`False`) + If :code:`True`, the ``node_list`` elements are checked for compatibility with the graph topology and node labeling conventions, an error is thrown if any node is incompatible or duplicates exist. In other words, only node_lists that specify subgraphs of the default (full yield) graph are permitted. - check_edge_list : bool (optional, default False) - If True, the edge_list elements are checked for compatibility with + check_edge_list : bool (optional, default :code:`False`) + If :code:`True`, the edge_list elements are checked for compatibility with the graph topology and node labeling conventions, an error is thrown if any edge is incompatible or duplicates exist. In other words, only edge_lists that specify subgraphs of the default @@ -111,17 +112,17 @@ def pegasus_graph(m, create_using=None, node_list=None, edge_list=None, data=Tru The maximum degree of this graph is 15. The number of nodes depends on multiple parameters; for example, - * `pegasus_graph(1)`: zero nodes - * `pegasus_graph(m, fabric_only=False)`: :math:`24m(m-1)` nodes - * `pegasus_graph(m, fabric_only=True)`: :math:`24m(m-1)-8(m-1)` nodes - * `pegasus_graph(m, nice_coordinates=True)`: :math:`24(m-1)^2` nodes + * :code:`pegasus_graph(1)`: zero nodes + * :code:`pegasus_graph(m, fabric_only=False)`: :math:`24m(m-1)` nodes + * :code:`pegasus_graph(m, fabric_only=True)`: :math:`24m(m-1)-8(m-1)` nodes + * :code:`pegasus_graph(m, nice_coordinates=True)`: :math:`24(m-1)^2` nodes Counting formulas for edges have a complicated dependency on parameter settings. Some example upper bounds are: - * `pegasus_graph(1, fabric_only=False)`: zero edges - * `pegasus_graph(m, fabric_only=False)`: :math:`12*(15*(m-1)^2 + m - 3)` - edges if m > 1 + * :code:`pegasus_graph(1, fabric_only=False)`: zero edges + * :code:`pegasus_graph(m, fabric_only=False)`: :math:`12*(15*(m-1)^2 + m - 3)` + edges if :math:`m > 1` Note that the formulas above are valid for default offset parameters. diff --git a/dwave_networkx/generators/zephyr.py b/dwave_networkx/generators/zephyr.py index fd7f32aa..a7c02d8c 100644 --- a/dwave_networkx/generators/zephyr.py +++ b/dwave_networkx/generators/zephyr.py @@ -33,7 +33,8 @@ ] def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, - data=True, coordinates=False, check_node_list=False, check_edge_list=False): + data=True, coordinates=False, check_node_list=False, + check_edge_list=False): """ Creates a Zephyr graph with grid parameter ``m`` and tile parameter ``t``. @@ -49,33 +50,33 @@ def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, If provided, this graph is cleared of nodes and edges and filled with the new graph. Usually used to set the type of the graph. node_list : iterable (optional, default None) - Iterable of nodes in the graph. If None, calculated from (``m``, ``t``) - and ``coordinates``. The nodes should be compatible with the requested - coordinate system and topology bounds; by default integer-labeled - in :code:`range(4 * t * m * (2 * m + 1))`. Nodes incompatible with - the requested topology are accepted by default. + Iterable of nodes in the graph. If not specified, calculated from (``m``, ``t``) + and ``coordinates``. The nodes should typically be compatible with the + requested lattice shape parameters and coordinate system, incompatible + nodes are accepted unless you set :code:`check_node_list=True`. If not + specified, all :math:`4 t m (2 m + 1)` nodes compatible with the + topology description are included. edge_list : iterable (optional, default None) - Iterable of edges in the graph. If None, calculated - from the ``node_list`` as described below. - Edges should be 2-tuples of nodes that match the - requested coordinate system and topology bounds. Edges are accepted by - default, provided component nodes are contained in the ``node_list``, - otherwise they are ignored. - data : bool, optional (default True) - If True, adds to each node an attribute with a format that depends on + Iterable of edges in the graph. Edges must be 2-tuples of the nodes + specified in node_list, or calculated from (``m``, ``t``) and ``coordinates`` + per the topology description below; incompatible edges are ignored + unless you set :code:`check_edge_list=True`. If not specified, all edges + compatible with the ``node_list`` and topology description are included. + data : bool, optional (default :code:`True`) + If :code:`True`, adds to each node an attribute with a format that depends on the ``coordinates`` parameter: a 5-tuple ``'zephyr_index'`` if - ``coordinates`` is False and an integer ``'linear_index'`` if ``coordinates`` - is True. - coordinates : bool, optional (default False) - If True, node labels are 5-tuple Zephyr indices. - check_node_list : bool (optional, default False) - If True, the node_list elements are checked for compatibility with + :code:`coordinates=False` and an integer ``'linear_index'`` if ``coordinates`` + is :code:`True`. + coordinates : bool, optional (default :code:`False`) + If :code:`True`, node labels are 5-tuple Zephyr indices. + check_node_list : bool (optional, default :code:`False`) + If :code:`True`, the ``node_list`` elements are checked for compatibility with the graph topology and node labeling conventions, an error is thrown if any node is incompatible or duplicates exist. In other words, only node_lists that specify subgraphs of the default (full yield) graph are permitted. - check_edge_list : bool (optional, default False) - If True, the edge_list elements are checked for compatibility with + check_edge_list : bool (optional, default :code:`False`) + If :code:`True`, the edge_list elements are checked for compatibility with the graph topology and node labeling conventions, an error is thrown if any edge is incompatible or duplicates exist. In other words, only edge_lists that specify subgraphs of the default From eb75f4dd2dbfbb3deb86b88635f924d730c4e676 Mon Sep 17 00:00:00 2001 From: jackraymond <10591246+jackraymond@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:49:36 -0700 Subject: [PATCH 06/15] Update dwave_networkx/generators/chimera.py Grammar Co-authored-by: Joel <34041130+JoelPasvolsky@users.noreply.github.com> --- dwave_networkx/generators/chimera.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwave_networkx/generators/chimera.py b/dwave_networkx/generators/chimera.py index 17e7fced..8e1b18dc 100644 --- a/dwave_networkx/generators/chimera.py +++ b/dwave_networkx/generators/chimera.py @@ -71,7 +71,7 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis attribute is a 4-tuple Chimera index as defined below. coordinates : bool (optional, default :code:`False`) If :code:`True`, node labels are 4-tuples, equivalent to the chimera_index - attribute as below. In this case, the `data` parameter controls the + attribute as below. In this case, the ``data`` parameter controls the existence of a `linear_index attribute`, which is an int. check_node_list : bool (optional, default :code:`False`) If :code:`True`, the ``node_list`` elements are checked for compatibility with From f97e7a81a135f6976f568991a8b50ff157b2311b Mon Sep 17 00:00:00 2001 From: jackraymond <10591246+jackraymond@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:49:49 -0700 Subject: [PATCH 07/15] Update dwave_networkx/generators/chimera.py Grammar Co-authored-by: Joel <34041130+JoelPasvolsky@users.noreply.github.com> --- dwave_networkx/generators/chimera.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwave_networkx/generators/chimera.py b/dwave_networkx/generators/chimera.py index 8e1b18dc..5e4a0733 100644 --- a/dwave_networkx/generators/chimera.py +++ b/dwave_networkx/generators/chimera.py @@ -54,8 +54,8 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis with the new graph. Usually used to set the type of the graph. node_list : iterable (optional, default None) Iterable of nodes in the graph. The nodes should typically be - compatible with the requested lattice shape parameters and coordinate - system, incompatible nodes are accepted unless you set :code:`check_node_list=True`. + compatible with the requested lattice-shape parameters and coordinate + system; incompatible nodes are accepted unless you set :code:`check_node_list=True`. If not specified, calculated from (``m``, ``n``, ``t``) and ``coordinates`` per the topology description below; all :math:`2 t m n` nodes are included. From 6f22d1d742bedf343823b64c3ed0b550d094e7c9 Mon Sep 17 00:00:00 2001 From: jackraymond <10591246+jackraymond@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:50:11 -0700 Subject: [PATCH 08/15] Update dwave_networkx/generators/chimera.py Missing argument formatting Co-authored-by: Joel <34041130+JoelPasvolsky@users.noreply.github.com> --- dwave_networkx/generators/chimera.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwave_networkx/generators/chimera.py b/dwave_networkx/generators/chimera.py index 5e4a0733..866b4edc 100644 --- a/dwave_networkx/generators/chimera.py +++ b/dwave_networkx/generators/chimera.py @@ -61,7 +61,7 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis nodes are included. edge_list : iterable (optional, default None) Iterable of edges in the graph. Edges must be 2-tuples of the nodes - specified in node_list, or calculated from (``m``, ``n``, ``t``) and + specified in ``node_list``, or calculated from (``m``, ``n``, ``t``) and ``coordinates`` per the topology description below; incompatible edges are ignored unless you set :code:`check_edge_list=True`. If not specified, all edges compatible with the ``node_list`` and topology From 0d3d876b7507c815bb2a3813c9c2dcbb3735cac8 Mon Sep 17 00:00:00 2001 From: jackraymond <10591246+jackraymond@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:50:39 -0700 Subject: [PATCH 09/15] Update dwave_networkx/generators/chimera.py inappropriate abbreviation in docstring Co-authored-by: Joel <34041130+JoelPasvolsky@users.noreply.github.com> --- dwave_networkx/generators/chimera.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwave_networkx/generators/chimera.py b/dwave_networkx/generators/chimera.py index 866b4edc..6e7a0abf 100644 --- a/dwave_networkx/generators/chimera.py +++ b/dwave_networkx/generators/chimera.py @@ -72,7 +72,7 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis coordinates : bool (optional, default :code:`False`) If :code:`True`, node labels are 4-tuples, equivalent to the chimera_index attribute as below. In this case, the ``data`` parameter controls the - existence of a `linear_index attribute`, which is an int. + existence of a `linear_index attribute`, which is an integer. check_node_list : bool (optional, default :code:`False`) If :code:`True`, the ``node_list`` elements are checked for compatibility with the graph topology and node labeling conventions, and an error is thrown From 14a119f0cc6e558475604a04f6af3b7d702c4652 Mon Sep 17 00:00:00 2001 From: jackraymond <10591246+jackraymond@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:50:55 -0700 Subject: [PATCH 10/15] Update dwave_networkx/generators/chimera.py Missing markup in docstrings Co-authored-by: Joel <34041130+JoelPasvolsky@users.noreply.github.com> --- dwave_networkx/generators/chimera.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwave_networkx/generators/chimera.py b/dwave_networkx/generators/chimera.py index 6e7a0abf..950faa0f 100644 --- a/dwave_networkx/generators/chimera.py +++ b/dwave_networkx/generators/chimera.py @@ -80,7 +80,7 @@ def chimera_graph(m, n=None, t=None, create_using=None, node_list=None, edge_lis In other words, the ``node_list`` must specify a subgraph of the full-yield graph described below. check_edge_list : bool (optional, default :code:`False`) - If :code:`True`, the edge_list elements are checked for compatibility with + If :code:`True`, the ``edge_list`` elements are checked for compatibility with the graph topology and node labeling conventions, an error is thrown if any edge is incompatible or duplicates exist. In other words, the ``edge_list`` must specify a subgraph of the From 3cbc036a2d593596676ee5f90824b514d9906a53 Mon Sep 17 00:00:00 2001 From: jackraymond <10591246+jackraymond@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:51:10 -0700 Subject: [PATCH 11/15] Update dwave_networkx/generators/zephyr.py Typo in docstring Co-authored-by: Joel <34041130+JoelPasvolsky@users.noreply.github.com> --- dwave_networkx/generators/zephyr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwave_networkx/generators/zephyr.py b/dwave_networkx/generators/zephyr.py index a7c02d8c..d16970af 100644 --- a/dwave_networkx/generators/zephyr.py +++ b/dwave_networkx/generators/zephyr.py @@ -71,7 +71,7 @@ def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, If :code:`True`, node labels are 5-tuple Zephyr indices. check_node_list : bool (optional, default :code:`False`) If :code:`True`, the ``node_list`` elements are checked for compatibility with - the graph topology and node labeling conventions, an error is thrown + the graph topology and node labeling conventions, and an error is thrown if any node is incompatible or duplicates exist. In other words, only node_lists that specify subgraphs of the default (full yield) graph are permitted. From b20d3bbcd64433040e74dbe12ada356ff6620678 Mon Sep 17 00:00:00 2001 From: jackraymond <10591246+jackraymond@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:51:23 -0700 Subject: [PATCH 12/15] Update dwave_networkx/generators/zephyr.py Typo in docstrings Co-authored-by: Joel <34041130+JoelPasvolsky@users.noreply.github.com> --- dwave_networkx/generators/zephyr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwave_networkx/generators/zephyr.py b/dwave_networkx/generators/zephyr.py index d16970af..2d9774ca 100644 --- a/dwave_networkx/generators/zephyr.py +++ b/dwave_networkx/generators/zephyr.py @@ -77,7 +77,7 @@ def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, (full yield) graph are permitted. check_edge_list : bool (optional, default :code:`False`) If :code:`True`, the edge_list elements are checked for compatibility with - the graph topology and node labeling conventions, an error is thrown + the graph topology and node labeling conventions, and an error is thrown if any edge is incompatible or duplicates exist. In other words, only edge_lists that specify subgraphs of the default (full yield) graph are permitted. From dc2e175fad17730a7050238d2fa44b3215b9e72f Mon Sep 17 00:00:00 2001 From: jackraymond <10591246+jackraymond@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:51:44 -0700 Subject: [PATCH 13/15] Update dwave_networkx/generators/zephyr.py Typos and markup omissions Co-authored-by: Joel <34041130+JoelPasvolsky@users.noreply.github.com> --- dwave_networkx/generators/zephyr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwave_networkx/generators/zephyr.py b/dwave_networkx/generators/zephyr.py index 2d9774ca..f6e528c4 100644 --- a/dwave_networkx/generators/zephyr.py +++ b/dwave_networkx/generators/zephyr.py @@ -73,8 +73,8 @@ def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, If :code:`True`, the ``node_list`` elements are checked for compatibility with the graph topology and node labeling conventions, and an error is thrown if any node is incompatible or duplicates exist. - In other words, only node_lists that specify subgraphs of the default - (full yield) graph are permitted. + In other words, ``node_lists`` must specify a subgraph of the default + (full yield) graph described below. check_edge_list : bool (optional, default :code:`False`) If :code:`True`, the edge_list elements are checked for compatibility with the graph topology and node labeling conventions, and an error is thrown From 32a0164b4701396e6f834e04ca557751382f5dbe Mon Sep 17 00:00:00 2001 From: jackraymond <10591246+jackraymond@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:52:02 -0700 Subject: [PATCH 14/15] Update dwave_networkx/generators/zephyr.py Markup and grammar Co-authored-by: Joel <34041130+JoelPasvolsky@users.noreply.github.com> --- dwave_networkx/generators/zephyr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwave_networkx/generators/zephyr.py b/dwave_networkx/generators/zephyr.py index f6e528c4..551300c2 100644 --- a/dwave_networkx/generators/zephyr.py +++ b/dwave_networkx/generators/zephyr.py @@ -76,7 +76,7 @@ def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, In other words, ``node_lists`` must specify a subgraph of the default (full yield) graph described below. check_edge_list : bool (optional, default :code:`False`) - If :code:`True`, the edge_list elements are checked for compatibility with + If :code:`True`, ``edge_list`` elements are checked for compatibility with the graph topology and node labeling conventions, and an error is thrown if any edge is incompatible or duplicates exist. In other words, only edge_lists that specify subgraphs of the default From b13a571b2317acf912647d31ec433d493972b972 Mon Sep 17 00:00:00 2001 From: jackraymond <10591246+jackraymond@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:52:19 -0700 Subject: [PATCH 15/15] Update dwave_networkx/generators/zephyr.py Markup and grammar Co-authored-by: Joel <34041130+JoelPasvolsky@users.noreply.github.com> --- dwave_networkx/generators/zephyr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwave_networkx/generators/zephyr.py b/dwave_networkx/generators/zephyr.py index 551300c2..069c510c 100644 --- a/dwave_networkx/generators/zephyr.py +++ b/dwave_networkx/generators/zephyr.py @@ -79,8 +79,8 @@ def zephyr_graph(m, t=4, create_using=None, node_list=None, edge_list=None, If :code:`True`, ``edge_list`` elements are checked for compatibility with the graph topology and node labeling conventions, and an error is thrown if any edge is incompatible or duplicates exist. - In other words, only edge_lists that specify subgraphs of the default - (full yield) graph are permitted. + In other words, ``edge_list`` must specify a subgraph of the default + (full yield) graph described below. Returns -------