コード例 #1
0
    def test_tile_around_edge_defects_pegasus(self):
        pegasus_shape = [5]

        # P5 structured sampler with one missing external edge that does not p
        # prevent tesselation of 2x2 blocks (12 tiles, equivalent to full yield)
        broken_edges_nice_coordinates = [(0, 1, 0, 0, 0), (0, 2, 0, 0, 0)]
        broken_edges = [
            tuple(
                dnx.pegasus_coordinates(pegasus_shape[0]).nice_to_linear(coord)
                for coord in broken_edges_nice_coordinates)
        ]
        mock_sampler = MockDWaveSampler(topology_type='pegasus',
                                        topology_shape=pegasus_shape,
                                        broken_edges=broken_edges)
        sampler = TilingComposite(mock_sampler, 2, 2, 4)
        self.assertTrue(len(sampler.embeddings) == 12)

        # P5 structured sampler with one missing internal edge that prevents
        # tesselation of 2x2 blocks (otherwise 12 tiles, with edge defect 11)
        broken_edge_nice_coordinates = [(0, 0, 0, 0, 0), (0, 0, 0, 1, 0)]
        broken_edges = [
            tuple(
                dnx.pegasus_coordinates(pegasus_shape[0]).nice_to_linear(coord)
                for coord in broken_edge_nice_coordinates)
        ]
        mock_sampler = MockDWaveSampler(topology_type='pegasus',
                                        topology_shape=pegasus_shape,
                                        broken_edges=broken_edges)
        sampler = TilingComposite(mock_sampler, 2, 2, 4)
        self.assertTrue(len(sampler.embeddings) == 11)
コード例 #2
0
    def test_sublattice_mappings(self):
        def check_subgraph_mapping(f, g, h):
            for v in g:
                if not h.has_node(f(v)):
                    raise RuntimeError(
                        f"node {v} mapped to {f(v)} is not in {h.graph['name']} ({h.graph['labels']})"
                    )
            for u, v in g.edges:
                if not h.has_edge(f(u), f(v)):
                    raise RuntimeError(
                        f"edge {(u, v)} mapped to {(f(u), f(v))} not present in {h.graph['name']} ({h.graph['labels']})"
                    )

        coords5 = dnx.pegasus_coordinates(5)
        coords3 = dnx.pegasus_coordinates(3)

        p3l = dnx.pegasus_graph(3)
        p3c = dnx.pegasus_graph(3, coordinates=True)
        p3n = coords3.graph_to_nice(p3c)

        p5l = dnx.pegasus_graph(5)
        p5c = dnx.pegasus_graph(5, coordinates=True)
        p5n = coords5.graph_to_nice(p5c)

        for target in p5l, p5c, p5n:
            for source in p3l, p3c, p3n:
                covered = set()
                for f in dnx.pegasus_sublattice_mappings(source, target):
                    check_subgraph_mapping(f, source, target)
                    covered.update(map(f, source))
                self.assertEqual(covered, set(target))

        c2l = dnx.chimera_graph(2)
        c2c = dnx.chimera_graph(2, coordinates=True)
        c23l = dnx.chimera_graph(2, 3)
        c32c = dnx.chimera_graph(3, 2, coordinates=True)

        p5n = dnx.pegasus_graph(5, nice_coordinates=True)
        p5l = coords5.graph_to_linear(p5n)
        p5c = coords5.graph_to_pegasus(p5n)

        for target in p5l, p5c, p5n:
            for source in c2l, c2c, c23l, c32c, target:
                covered = set()
                for f in dnx.pegasus_sublattice_mappings(source, target):
                    check_subgraph_mapping(f, source, target)
                    covered.update(map(f, source))
                self.assertEqual(covered, set(target))
コード例 #3
0
    def test_tile_around_node_defects_pegasus(self):
        pegasus_shape = [5]
        # Create a pegasus P5 structured solver subject to node defects with the
        # following (nice-coordinate) 3x4x4 cell-level structure:
        # OOOX OOOO OOOO
        # OOOO OOOO OOOO
        # OOOO OOOO OOOO
        # OOOO OOOO OOOX
        # where O: complete cell, X: incomplete cell
        broken_node_nice_coordinates = [(0, 0, 3, 0, 1), (2, 3, 3, 1, 3)]
        broken_node_linear_coordinates = [
            dnx.pegasus_coordinates(pegasus_shape[0]).nice_to_linear(coord)
            for coord in broken_node_nice_coordinates
        ]
        mock_sampler = MockDWaveSampler(
            topology_type='pegasus',
            topology_shape=pegasus_shape,
            broken_nodes=broken_node_linear_coordinates)
        # Tile with 2x2 cells:
        sampler = TilingComposite(mock_sampler, 2, 2, 4)

        # Given the above pegasus graph, check that the embeddings are as
        # follows:
        # 00XX  3344 7788
        # 0011  3344 7788
        # 2211  5566 99XX
        # 22XX  5566 99XX

        # Check correct number of embeddings and size of each is sufficient,
        # given chimera test checks detailed position:
        self.assertTrue(len(sampler.embeddings) == 10)
        self.assertFalse(any([len(emb) != 32 for emb in sampler.embeddings]))
コード例 #4
0
    def test_nice_coordinates(self):
        G = dnx.pegasus_graph(4, nice_coordinates=True)
        H = dnx.chimera_graph(3, coordinates=True)
        for p, q in H.edges():
            for t in range(3):
                pg = (t, ) + p
                qg = (t, ) + q
                self.assertTrue(G.has_edge(pg, qg))
        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)
コード例 #5
0
    def test_consistent_linear_nice_pegasus(self):
        P4 = dnx.pegasus_graph(4, nice_coordinates=True)

        coords = dnx.pegasus_coordinates(4)

        # `.*_to_*` methods

        for n, data in P4.nodes(data=True):
            p = data['pegasus_index']
            i = data['linear_index']
            self.assertEqual(coords.nice_to_pegasus(n), p)
            self.assertEqual(coords.pegasus_to_nice(p), n)
            self.assertEqual(coords.nice_to_linear(n), i)
            self.assertEqual(coords.linear_to_nice(i), n)
            self.assertEqual(coords.linear_to_pegasus(i), p)
            self.assertEqual(coords.pegasus_to_linear(p), i)

        # `.iter_*_to_*` methods

        nlist, plist, ilist = zip(*((n, d['pegasus_index'], d['linear_index'])
                                    for n, d in P4.nodes(data=True)))
        self.assertEqual(tuple(coords.iter_nice_to_pegasus(nlist)), plist)
        self.assertEqual(tuple(coords.iter_pegasus_to_nice(plist)), nlist)
        self.assertEqual(tuple(coords.iter_nice_to_linear(nlist)), ilist)
        self.assertEqual(tuple(coords.iter_linear_to_nice(ilist)), nlist)
        self.assertEqual(tuple(coords.iter_pegasus_to_linear(plist)), ilist)
        self.assertEqual(tuple(coords.iter_linear_to_pegasus(ilist)), plist)

        # `.iter_*_to_*_pairs` methods

        nedgelist = []
        pedgelist = []
        iedgelist = []
        for u, v in P4.edges:
            nedgelist.append((u, v))
            pedgelist.append(
                (P4.nodes[u]['pegasus_index'], P4.nodes[v]['pegasus_index']))
            iedgelist.append(
                (P4.nodes[u]['linear_index'], P4.nodes[v]['linear_index']))

        self.assertEqual(list(coords.iter_nice_to_pegasus_pairs(nedgelist)),
                         pedgelist)
        self.assertEqual(list(coords.iter_pegasus_to_nice_pairs(pedgelist)),
                         nedgelist)
        self.assertEqual(list(coords.iter_nice_to_linear_pairs(nedgelist)),
                         iedgelist)
        self.assertEqual(list(coords.iter_linear_to_nice_pairs(iedgelist)),
                         nedgelist)
        self.assertEqual(list(coords.iter_pegasus_to_linear_pairs(pedgelist)),
                         iedgelist)
        self.assertEqual(list(coords.iter_linear_to_pegasus_pairs(iedgelist)),
                         pedgelist)
コード例 #6
0
    def test_coordinate_subgraphs(self):
        G = dnx.pegasus_graph(4)
        H = dnx.pegasus_graph(4, coordinates=True)
        coords = dnx.pegasus_coordinates(4)

        lmask = sample(list(G.nodes()), G.number_of_nodes() // 2)
        cmask = list(coords.iter_linear_to_pegasus(lmask))

        self.assertEqual(lmask, list(coords.iter_pegasus_to_linear(cmask)))

        Gm = dnx.pegasus_graph(4, node_list=lmask)
        Hm = dnx.pegasus_graph(4, node_list=cmask, coordinates=True)

        Gs = G.subgraph(lmask)
        Hs = H.subgraph(cmask)

        EG = sorted(map(sorted, Gs.edges()))
        EH = sorted(map(sorted, Hs.edges()))

        self.assertEqual(EG, sorted(map(sorted, Gm.edges())))
        self.assertEqual(EH, sorted(map(sorted, Hm.edges())))

        Gn = dnx.pegasus_graph(4, edge_list=EG)
        Hn = dnx.pegasus_graph(4, edge_list=EH, coordinates=True)

        Gnodes = Gn.nodes
        Hnodes = Hn.nodes
        for v in Gnodes:
            q = Gnodes[v]['pegasus_index']
            self.assertIn(q, Hnodes)
            self.assertEqual(Hnodes[q]['linear_index'], v)
            self.assertEqual(v, coords.pegasus_to_linear(q))
            self.assertEqual(q, coords.linear_to_pegasus(v))
        for q in Hnodes:
            v = Hnodes[q]['linear_index']
            self.assertIn(v, Gnodes)
            self.assertEqual(Gnodes[v]['pegasus_index'], q)
            self.assertEqual(v, coords.pegasus_to_linear(q))
            self.assertEqual(q, coords.linear_to_pegasus(v))

        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()))))
コード例 #7
0
    def __init__(self, *args, **kwargs):
        super(TestBusclique, self).__init__(*args, **kwargs)

        self.c16 = dnx.chimera_graph(16)
        self.p16 = dnx.pegasus_graph(16)
        self.c16c = dnx.chimera_graph(16, coordinates=True, data=False)
        self.c428 = dnx.chimera_graph(4, n=2, t=8)
        self.c248 = dnx.chimera_graph(2, n=4, t=8)
        self.c42A = dnx.chimera_graph(4, n=2, t=9)
        c4c_0 = subgraph_node_yield(dnx.chimera_graph(4, coordinates=True),
                                    .95)
        p4c_0 = subgraph_node_yield(dnx.pegasus_graph(4, coordinates=True),
                                    .95)
        c4c = [
            c4c_0,
            subgraph_edge_yield(c4c_0, .95),
            subgraph_edge_yield_few_bad(c4c_0, .95, 6)
        ]
        p4c = [
            p4c_0,
            subgraph_edge_yield(p4c_0, .95),
            subgraph_edge_yield_few_bad(p4c_0, .95, 6)
        ]

        p4coords = dnx.pegasus_coordinates(4)
        c4coords = dnx.chimera_coordinates(4, 4, 4)

        c4 = [
            relabel(c, c4coords.iter_chimera_to_linear,
                    c4coords.iter_chimera_to_linear_pairs, 4) for c in c4c
        ]

        p4 = [
            relabel(p, p4coords.iter_pegasus_to_linear,
                    p4coords.iter_pegasus_to_linear_pairs, 4) for p in p4c
        ]

        p4n = [
            relabel(p,
                    p4coords.iter_pegasus_to_nice,
                    p4coords.iter_pegasus_to_nice_pairs,
                    4,
                    nice_coordinates=True) for p in p4c
        ]

        self.c4, self.c4_nd, self.c4_d = list(zip(c4, c4c))
        self.p4, self.p4_nd, self.p4_d = list(zip(p4, p4c, p4n))
コード例 #8
0
 def test_coordinate_basics(self):
     G = dnx.pegasus_graph(4, fabric_only=False)
     H = dnx.pegasus_graph(4, coordinates=True, fabric_only=False)
     coords = dnx.pegasus_coordinates(4)
     Gnodes = G.nodes
     Hnodes = H.nodes
     for v in Gnodes:
         q = Gnodes[v]['pegasus_index']
         self.assertIn(q, Hnodes)
         self.assertEqual(Hnodes[q]['linear_index'], v)
         self.assertEqual(v, coords.pegasus_to_linear(q))
         self.assertEqual(q, coords.linear_to_pegasus(v))
     for q in Hnodes:
         v = Hnodes[q]['linear_index']
         self.assertIn(v, Gnodes)
         self.assertEqual(Gnodes[v]['pegasus_index'], q)
         self.assertEqual(v, coords.pegasus_to_linear(q))
         self.assertEqual(q, coords.linear_to_pegasus(v))
コード例 #9
0
    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)
コード例 #10
0
ファイル: pegasus.py プロジェクト: CharJon/GeCO
def _initialize_weights_pegasus(pegasus_graph, size, draw_inter_weight,
                                draw_intra_weight, draw_other_weight):
    # 'nice' coordinate indices names (as per d-wave's documentation):
    p_coor = dwave.pegasus_coordinates(size)

    for _from, _to in pegasus_graph.edges:
        _from_nice = p_coor.linear_to_nice(_from)
        _to_nice = p_coor.linear_to_nice(_to)
        if not in_chimera_subgraph(_from_nice, _to_nice):
            pegasus_graph.add_edge(_from, _to, weight=draw_other_weight())
        else:
            if in_same_chimera_tile(_from_nice, _to_nice):
                # edge from one side to the other (internal edge)
                if not on_same_side(_from_nice, _to_nice):
                    pegasus_graph.add_edge(_from,
                                           _to,
                                           weight=draw_intra_weight())
                else:  # odd couplers
                    pegasus_graph.add_edge(_from,
                                           _to,
                                           weight=draw_other_weight())
            else:
                pegasus_graph.add_edge(_from, _to, weight=draw_inter_weight())
コード例 #11
0
ファイル: tiling.py プロジェクト: pau557/dwave-system
    def __init__(self, sampler, sub_m, sub_n, t=4):

        self.parameters = sampler.parameters.copy()
        self.properties = properties = {'child_properties': sampler.properties}

        tile = dnx.chimera_graph(sub_m, sub_n, t)
        self.nodelist = sorted(tile.nodes)
        self.edgelist = sorted(sorted(edge) for edge in tile.edges)
        # dimod.Structured abstract base class automatically populates adjacency
        # and structure as mixins based on nodelist and edgelist

        if not isinstance(sampler, dimod.Structured):
            # we could also just tile onto the unstructured sampler but in that
            # case we would need to know how many tiles to use
            raise ValueError("given child sampler should be structured")
        self.children = [sampler]
        # Chimera values (unless pegasus specified)
        num_sublattices = 1
        nodes_per_cell = t * 2
        edges_per_cell = t * t
        if not ('topology' in sampler.properties
                and 'type' in sampler.properties['topology']
                and 'shape' in sampler.properties['topology']):
            raise ValueError('To use this composite it is necessary for the'
                             'structured sampler to have an explicit topology'
                             '(sampler.properties[\'topology\']). Necessary'
                             'fields are \'type\' and \'shape\'. ')
        if sampler.properties['topology']['type'] == 'chimera':
            if len(sampler.properties['topology']['shape']) != 3:
                raise ValueError('topology shape is not of length 3 '
                                 '(not compatible with chimera)')
            if sampler.properties['topology']['shape'][2] != t:
                raise ValueError('Tiling methodology requires that solver'
                                 'and subproblem have identical shore size')
            m = sampler.properties['topology']['shape'][0]
            n = sampler.properties['topology']['shape'][1]
        else:
            if len(sampler.properties['topology']['shape']) != 1:
                raise ValueError('topology shape is not of length 1 '
                                 '(not compatible with pegasus)')
            # Full yield in odd-couplers also required.
            # Generalizes chimera subgraph requirement and leads to some
            # simplification of expressions, but at with a cost in cell-yield
            edges_per_cell += t
            # Square solvers only by pegasus lattice definition PN yields
            # 3 by N-1 by N-1 cells:
            num_sublattices = 3
            m = n = sampler.properties['topology']['shape'][0] - 1
            if t != 4:
                raise ValueError(
                    't=4 for all pegasus processors, value is not typically'
                    'stored in solver properties and is difficult to infer.'
                    'Therefore only the value t=4 is supported.')

        if num_sublattices == 1:
            # Chimera defaults. Appended coordinates (treat as first and only sublattice)
            system = dnx.chimera_graph(m,
                                       n,
                                       t,
                                       node_list=sampler.structure.nodelist,
                                       edge_list=sampler.structure.edgelist)

            c2i = {(0, *chimera_index): linear_index
                   for (linear_index,
                        chimera_index) in system.nodes(data='chimera_index')}
        else:
            system = dnx.pegasus_graph(m,
                                       node_list=sampler.structure.nodelist,
                                       edge_list=sampler.structure.edgelist)
            # Vector specification in terms of nice coordinates:
            c2i = {
                dnx.pegasus_coordinates(m + 1).linear_to_nice(linear_index):
                linear_index
                for linear_index in system.nodes()
            }

        sub_c2i = {
            chimera_index: linear_index
            for (linear_index,
                 chimera_index) in tile.nodes(data='chimera_index')
        }

        # Count the connections between these qubits
        def _between(qubits1, qubits2):
            edges = [
                edge for edge in system.edges
                if edge[0] in qubits1 and edge[1] in qubits2
            ]
            return len(edges)

        # Get the list of qubits in a cell
        def _cell_qubits(s, i, j):
            return [
                c2i[(s, i, j, u, k)] for u in range(2) for k in range(t)
                if (s, i, j, u, k) in c2i
            ]

        # get a mask of complete cells
        cells = [[[False for _ in range(n)] for _ in range(m)]
                 for _ in range(num_sublattices)]

        for s in range(num_sublattices):
            for i in range(m):
                for j in range(n):
                    qubits = _cell_qubits(s, i, j)
                    cells[s][i][j] = (len(qubits) == nodes_per_cell
                                      and _between(qubits,
                                                   qubits) == edges_per_cell)

        # List of 'embeddings'
        self.embeddings = properties['embeddings'] = embeddings = []

        # For each possible chimera cell check if the next few cells are complete
        for s in range(num_sublattices):
            for i in range(m + 1 - sub_m):
                for j in range(n + 1 - sub_n):

                    # Check if the sub cells are matched
                    match = all(cells[s][i + sub_i][j + sub_j]
                                for sub_i in range(sub_m)
                                for sub_j in range(sub_n))

                    # Check if there are connections between the cells.
                    # Both Pegasus and Chimera have t vertical and t horizontal between cells:
                    for sub_i in range(sub_m):
                        for sub_j in range(sub_n):
                            if sub_m > 1 and sub_i < sub_m - 1:
                                match &= _between(
                                    _cell_qubits(s, i + sub_i, j + sub_j),
                                    _cell_qubits(s, i + sub_i + 1,
                                                 j + sub_j)) == t
                            if sub_n > 1 and sub_j < sub_n - 1:
                                match &= _between(
                                    _cell_qubits(s, i + sub_i, j + sub_j),
                                    _cell_qubits(s, i + sub_i,
                                                 j + sub_j + 1)) == t

                    if match:
                        # Pull those cells out into an embedding.
                        embedding = {}
                        for sub_i in range(sub_m):
                            for sub_j in range(sub_n):
                                cells[s][i + sub_i][
                                    j + sub_j] = False  # Mark cell as matched
                                for u in range(2):
                                    for k in range(t):
                                        embedding[sub_c2i[sub_i, sub_j, u,
                                                          k]] = {
                                                              c2i[(s,
                                                                   i + sub_i,
                                                                   j + sub_j,
                                                                   u, k)]
                                                          }

                        embeddings.append(embedding)

        if len(embeddings) == 0:
            raise ValueError("no tile embeddings found; "
                             "is the sampler Pegasus or Chimera structured?")
コード例 #12
0
import dwave_networkx as dnx
from dwave.system.samplers import DWaveSampler

dwave_sampler_pegasus = DWaveSampler(solver={'topology__type': 'pegasus'})
props_pegasus = dwave_sampler_pegasus.properties

# Get total qubits - should be 24 * N * (N - 1)
total_qubits = props_pegasus['num_qubits']

# Get total number of inactive qubits
total_inactive = [
    i for i in range(total_qubits) if i not in dwave_sampler_pegasus.nodelist
]
print(len(total_inactive))

# This should convert the known inactive qubit indices to Pegasus coordinates.
inactive_pegasus_coord = [
    dnx.pegasus_coordinates(16).linear_to_pegasus(k) for k in total_inactive
]

# With coordinates=True, we only get the fabric qubits
pegasus_graph = dnx.pegasus_graph(16, coordinates=True)
active_fabric = [
    node for node in pegasus_graph.nodes if node not in inactive_pegasus_coord
]
print(len(active_fabric))

# another way to compute the number of active qubits
active_qubits = dwave_sampler_pegasus.solver.num_active_qubits
print(active_qubits)
コード例 #13
0
ファイル: placement.py プロジェクト: boothby/minorminer
def _lookup_intersection_coordinates(G):
    """For a dwave_networkx graph G, this returns a dictionary mapping the 
    lattice points to sets of vertices of G. 
    
    For Chimera, Pegasus and Zephyr, each lattice point corresponds to the 2
    qubits intersecting at that point.
    """
    graph_data = G.graph
    family = graph_data.get("family")
    data_key = None
    intersection_points = defaultdict(set)
    if family == "chimera":
        shore = graph_data.get("tile")
        collect_intersection_points = _chimera_all_intersection_points
        if graph_data["labels"] == "coordinate":

            def get_coords(v):
                return v
        elif graph_data["data"]:
            data_key = "chimera_index"
        else:
            coords = dnx.chimera_coordinates(graph_data['rows'],
                                             n=graph_data['columns'],
                                             t=shore)
            get_coords = coords.linear_to_chimera
    elif family == "pegasus":
        shore = [
            graph_data['vertical_offsets'], graph_data['horizontal_offsets']
        ]
        collect_intersection_points = _pegasus_all_intersection_points
        if graph_data["labels"] == "coordinate":

            def get_coords(v):
                return v
        elif graph_data["data"]:
            data_key = "pegasus_index"
        else:
            coords = dnx.pegasus_coordinates(graph_data['rows'])
            if graph_data['labels'] == 'int':
                get_coords = coords.linear_to_pegasus
            elif graph_data['labels'] == 'nice':
                get_coords = coords.nice_to_pegasus
    elif family == "zephyr":
        shore = graph_data.get("tile")
        collect_intersection_points = _zephyr_all_intersection_points
        if graph_data["labels"] == "coordinate":

            def get_coords(v):
                return v
        elif graph_data["data"]:
            data_key = "zephyr_index"
        else:
            coords = dnx.zephyr_coordinates(graph_data['rows'], t=shore)
            get_coords = coords.linear_to_zephyr

    if data_key is None:
        for v in G:
            collect_intersection_points(intersection_points, shore, v,
                                        *get_coords(v))
    else:
        for v, d in G.nodes(data=True):
            collect_intersection_points(intersection_points, shore, v,
                                        *d[data_key])

    return intersection_points
コード例 #14
0
def make_origin_embeddings(qpu_sampler=None, lattice_type=None):
    """Creates optimal embeddings for a lattice.

    The embeddings created are compatible with the topology and shape of a
    specified ``qpu_sampler``.

    Args:
        qpu_sampler (:class:`dimod.Sampler`, optional):
            Quantum sampler such as a D-Wave system. If not specified, the
            :class:`~dwave.system.samplers.DWaveSampler` sampler class is used 
            to select a QPU solver with a topology compatible with the specified
            ``lattice_type`` (e.g. an Advantage system for a 'pegasus' lattice 
            type).

        lattice_type (str, optional, default=qpu_sampler.properties['topology']['type']):
            Options are:
                * "cubic"
                    Embeddings compatible with the schemes arXiv:2009.12479 and
                    arXiv:2003.00133 are created for a ``qpu_sampler`` of
                    topology type either 'pegasus' or 'chimera'.

                * "pegasus"
                    Embeddings are chain length one (minimal and native).
                    If ``qpu_sampler`` topology type is 'pegasus', maximum
                    scale subgraphs are embedded using the ``nice_coordinates``
                    vector labeling scheme for variables.

                * "chimera"
                    Embeddings are chain length one (minimal and native).
                    If ``qpu_sampler`` topology type is 'chimera', maximum
                    scale chimera subgraphs are embedded using the chimera
                    vector labeling scheme for variables.

    Returns:
        A list of embeddings. Each embedding is a dictionary, mapping
        geometric problem keys to sets of qubits (chains) compatible with
        the ``qpu_sampler``.

    Examples:
        This example creates a list of three cubic lattice embeddings
        compatible with the default online system. These three embeddings are
        related by rotation of the lattice: for a Pegasus P16 system the
        embeddings are for lattices of size (15,15,12), (12,15,15) and (15,12,15)
        respectively.

        >>> from dwave.system.samplers import DWaveSampler   # doctest: +SKIP
        >>> sampler = DWaveSampler()  # doctest: +SKIP
        >>> embeddings = make_origin_embeddings(qpu_sampler=sampler,
        ...                                     lattice_type='cubic')  # doctest: +SKIP

    """
    if qpu_sampler is None:
        if lattice_type == 'pegasus' or lattice_type == 'chimera':
            qpu_sampler = DWaveSampler(solver={'topology__type': lattice_type})
        else:
            qpu_sampler = DWaveSampler()

    qpu_type = qpu_sampler.properties['topology']['type']
    if lattice_type is None:
        lattice_type = qpu_type
    qpu_shape = qpu_sampler.properties['topology']['shape']

    target = nx.Graph()
    target.add_edges_from(qpu_sampler.edgelist)

    if qpu_type == lattice_type:
        # Fully yielded fully utilized native topology problem.
        # This method is also easily adapted to work for any chain-length 1
        # embedding
        origin_embedding = {q: [q] for q in qpu_sampler.properties['qubits']}
        if lattice_type == 'pegasus':
            # Trimming to nice_coordinate supported embeddings is not a unique,
            # options, it has some advantages and some disadvantages:
            proposed_source = dnx.pegasus_graph(qpu_shape[0],
                                                nice_coordinates=True)
            proposed_source = nx.relabel_nodes(
                proposed_source, {
                    q: dnx.pegasus_coordinates(qpu_shape[0]).nice_to_linear(q)
                    for q in proposed_source.nodes()
                })
            lin_to_vec = dnx.pegasus_coordinates(qpu_shape[0]).linear_to_nice

        elif lattice_type == 'chimera':
            proposed_source = dnx.chimera_graph(qpu_shape[0], qpu_shape[1],
                                                qpu_shape[2])
            lin_to_vec = dnx.chimera_coordinates(
                qpu_shape[0]).linear_to_chimera
        else:
            raise ValueError(
                f'Unsupported native processor topology {qpu_type}. '
                'Support for Zephyr and other topologies is straightforward to '
                'add subject to standard dwave_networkx library tool availability.'
            )

    elif lattice_type == 'cubic':
        if qpu_type == 'pegasus':
            vec_to_lin = dnx.pegasus_coordinates(
                qpu_shape[0]).pegasus_to_linear
            L = qpu_shape[0] - 1
            dimensions = [L, L, 12]
            # See arXiv:2003.00133
            origin_embedding = {
                (x, y, z): [
                    vec_to_lin((0, x, z + 4, y)),
                    vec_to_lin((1, y + 1, 7 - z, x))
                ]
                for x in range(L) for y in range(L) for z in range(8)
                if target.has_edge(vec_to_lin((
                    0, x, z + 4, y)), vec_to_lin((1, y + 1, 7 - z, x)))
            }
            origin_embedding.update({
                (x, y, z): [
                    vec_to_lin((0, x + 1, z - 8, y)),
                    vec_to_lin((1, y, 19 - z, x))
                ]
                for x in range(L) for y in range(L) for z in range(8, 12)
                if target.has_edge(vec_to_lin((
                    0, x + 1, z - 8, y)), vec_to_lin((1, y, 19 - z, x)))
            })
        elif qpu_type == 'chimera':
            vec_to_lin = dnx.chimera_coordinates(
                qpu_shape[0], qpu_shape[1], qpu_shape[2]).chimera_to_linear
            L = qpu_shape[0] // 2
            dimensions = [L, L, 8]
            # See arxiv:2009.12479, one choice amongst many
            origin_embedding = {
                (x, y, z): [
                    vec_to_lin(coord)
                    for coord in [(2 * x + 1, 2 * y, 0,
                                   z), (2 * x, 2 * y, 0,
                                        z), (2 * x, 2 * y, 1,
                                             z), (2 * x, 2 * y + 1, 1, z)]
                ]
                for x in range(L) for y in range(L) for z in range(4)
                if target.has_edge(vec_to_lin((
                    2 * x + 1, 2 * y, 0, z)), vec_to_lin((2 * x, 2 * y, 0, z)))
                and target.has_edge(vec_to_lin((
                    2 * x, 2 * y, 0, z)), vec_to_lin((2 * x, 2 * y, 1, z)))
                and target.has_edge(vec_to_lin((
                    2 * x, 2 * y, 1, z)), vec_to_lin((2 * x, 2 * y + 1, 1, z)))
            }
            origin_embedding.update({
                (x, y, 4 + z): [
                    vec_to_lin(coord)
                    for coord in [(2 * x + 1, 2 * y, 1,
                                   z), (2 * x + 1, 2 * y + 1, 1,
                                        z), (2 * x + 1, 2 * y + 1, 0,
                                             z), (2 * x, 2 * y + 1, 0, z)]
                ]
                for x in range(L) for y in range(L) for z in range(4)
                if target.has_edge(vec_to_lin((
                    2 * x + 1, 2 * y, 1,
                    z)), vec_to_lin((2 * x + 1, 2 * y + 1, 1, z)))
                and target.has_edge(vec_to_lin((
                    2 * x + 1, 2 * y + 1, 1,
                    z)), vec_to_lin((2 * x + 1, 2 * y + 1, 0, z))) and target.
                has_edge(vec_to_lin((2 * x + 1, 2 * y + 1, 0,
                                     z)), vec_to_lin((2 * x, 2 * y + 1, 0, z)))
            })
        else:
            raise ValueError(f'Unsupported qpu_sampler topology {qpu_type} '
                             'for cubic lattice solver')

        proposed_source = _make_cubic_lattice(dimensions)
    else:
        raise ValueError('Unsupported combination of lattice_type '
                         'and qpu_sampler topology')

    origin_embedding = _yield_limited_origin_embedding(origin_embedding,
                                                       proposed_source, target)

    if qpu_type == lattice_type:
        # Convert keys to standard vector scheme:
        origin_embedding = {
            lin_to_vec(node): origin_embedding[node]
            for node in origin_embedding
        }

    # We can propose additional embeddings. Or we can use symmetries of the
    # target graph (automorphisms), to create additional embedding options.
    # This is important in the cubic case, because the subregion shape and
    # embedding features are asymmetric in the x, y and z directions.
    # Various symmetries can be exploited in all lattices.
    origin_embeddings = [origin_embedding]
    if lattice_type == 'cubic':
        # A rotation is sufficient for demonstration purposes:
        origin_embeddings.append({(key[2], key[0], key[1]): value
                                  for key, value in origin_embedding.items()})
        origin_embeddings.append({(key[1], key[2], key[0]): value
                                  for key, value in origin_embedding.items()})
    elif lattice_type == 'pegasus':
        # A horizontal to vertical flip is sufficient for demonstration purposes:       # Flip north-east to south-west axis (see draw_pegasus):
        L = qpu_shape[0]
        origin_embeddings.append({(key[0], L - 2 - key[2], L - 2 - key[1],
                                   1 - key[3], 3 - key[4]): value
                                  for key, value in origin_embedding.items()})

    else:
        # A horizontal to vertical flip is sufficient for demonstration purposes:
        origin_embeddings.append({(key[1], key[0], 1 - key[2], key[3]): value
                                  for key, value in origin_embedding.items()})

    return origin_embeddings