Skip to content

Commit

Permalink
Merge pull request #296 from jackraymond/master
Browse files Browse the repository at this point in the history
Modify cubic lattice embedding on Zephyr, strengthen tests
  • Loading branch information
randomir authored Sep 11, 2024
2 parents 5ee88bd + 5eeb1fb commit 60cb28d
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 17 deletions.
35 changes: 23 additions & 12 deletions hybrid/decomposers.py
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,6 @@ def _yield_limited_origin_embedding(origin_embedding, proposed_source, target):
unyielded_edge_set = _unyielded_conditional_edges(emb=origin_embedding,
source=proposed_source,
target=target)

# Remove minimal number of nodes such that edges yielded on subgraph:
G = nx.Graph()
G.add_edges_from(unyielded_edge_set)
Expand Down Expand Up @@ -888,6 +887,12 @@ def _chimeralike_to_zephyr(coord: Tuple[int, int, int, int],
z = (r + c - w - j) // 2
return u, w, k, j, z

def _chimeralike_to_linear(coord: Tuple[int, int, int, int], m,
t: int=4, half_offset: int=1) -> int:
return dnx.zephyr_coordinates(m,t).zephyr_to_linear(
_chimeralike_to_zephyr(coord=coord,
t=t, half_offset=half_offset))

def _squarenextneighbor_node_to_zephyr_chain(row: int, col: int) -> Tuple[
Tuple[int, int, int, int], Tuple[int, int, int, int]]:
""""Embed a node into a chain for a grid plus next-neighbors lattice.
Expand Down Expand Up @@ -1027,7 +1032,7 @@ def make_origin_embeddings(qpu_sampler=None, lattice_type=None,
* "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'.
topology type 'zephyr', 'pegasus' or 'chimera'.
* "kings"
Embedding compatible with arXiv:2003.00133.pdf Table 1,
Expand Down Expand Up @@ -1160,14 +1165,23 @@ def make_origin_embeddings(qpu_sampler=None, lattice_type=None,

elif lattice_type == 'cubic':
if qpu_type == 'zephyr':
vec_to_lin = dnx.zephyr_coordinates(*qpu_shape).zephyr_to_linear
L = max(1, qpu_shape[0]-1)
_, t = qpu_shape
dimensions = [L, L, 4*t]
# A suitable, but not unique, scheme for L ~ 16 at chain length 2.
m, t = qpu_shape
vec_to_lin = lambda coord: _chimeralike_to_linear(coord, m=m, t=t)
# In the chimera like scheme each
# block (x,y,*) maps to four cells
# (x, y, z=[0,t)), (x,y, z=[t,2t)),
# (x, y, z=[2t,3t)), (x, y, z=[3t,4t))
# and supports x and y coupling to other blocks via
# external couplers. A sufficient scheme is
# thus similar to pegasus and chimera.
dimensions = [m, m, 4*t]
# A suitable, but not unique, scheme for L = m ~ 16 at chain length 2.
quadrant_map = {0 : (0, 0), 1: (0, 1), 2: (1, 1), 3: (1, 0)}
def zephyr_chain(x, y, z):
return (vec_to_lin((0, 2*y + (z//t)%2, z%t, z//(2*t), x)),
vec_to_lin((1, 2*x + (z//t)%2, z%t, z//(2*t), y)))
i = 2*x + quadrant_map[z%4][0]
j = 2*y + quadrant_map[z%4][1]
k = z//4 # Many permutations in z allow for periodic boundaries
return tuple(vec_to_lin((i, j, u, k)) for u in range(2))
origin_embedding = {coord: c
for coord in product(*map(range, dimensions))
if target.has_edge(*(c := zephyr_chain(*coord)))}
Expand Down Expand Up @@ -1223,7 +1237,6 @@ def pegasus_chain2(x, y, z):
else:
raise ValueError(f'Unsupported qpu_sampler topology {qpu_type} '
'for cubic lattice solver')

proposed_source = _make_cubic_lattice(dimensions)
elif lattice_type == 'kings':
if qpu_type == 'pegasus':
Expand Down Expand Up @@ -1254,12 +1267,10 @@ def pegasus_chain2(x, y, z):
else:
raise ValueError(f'Unsupported combination of {lattice_type} '
f'and qpu_sampler topology ({topology})')

if not allow_unyielded_edges:
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]
Expand Down
26 changes: 21 additions & 5 deletions tests/test_decomposers.py
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ def test_all_embeddings_validity(self):
# scale (hence inclusive of all keys).
if lattice_type == 'cubic':
if qpu_top == 'zephyr':
cubic_dims = (max(qpu_scale-1,1), max(qpu_scale-1,1), 16)
cubic_dims = (qpu_scale, qpu_scale, 16)
elif qpu_top == 'pegasus':
cubic_dims = (qpu_scale-1, qpu_scale-1, 12)
else:
Expand All @@ -819,17 +819,33 @@ def test_all_embeddings_validity(self):

elif lattice_type == 'pegasus':
proposed_source = dnx.pegasus_graph(qpu_scale,
fabric_only=True)
nice_coordinates=True)
else:
proposed_source = dnx.chimera_graph(qpu_scale)
proposed_source = dnx.chimera_graph(qpu_scale, coordinates=True)

qpu_sampler = MockDWaveSampler(
topology_type=qpu_top,
topology_shape=qpu_shape)


orig_embs = make_origin_embeddings(qpu_sampler=qpu_sampler,
lattice_type=lattice_type)

# No defects should be happy with all chains, and all edges,
# for full graph
for orig_emb in orig_embs:
self.assertEqual(len(list(orig_emb.keys())),
proposed_source.number_of_nodes())
# NB, only emb[0] due to technicality
orig_emb = orig_embs[0]
self.assertTrue(verify_embedding(
emb=orig_emb,
source=proposed_source,
target=qpu_sampler.properties['couplers']),
f'{qpu_top} and {lattice_type}')

# With defects, should be happy on subgraph
for _ in range(15):
qpu_sampler.edgelist.pop()

orig_embs = make_origin_embeddings(qpu_sampler=qpu_sampler,
lattice_type=lattice_type)
for orig_emb in orig_embs:
Expand Down

0 comments on commit 60cb28d

Please sign in to comment.