A lot of specific problems are tailored to specific hardware topologies of qubits; or a problem is defined on a structured topology and mapped to a hardware topology. Specific examples:
When discussing a hardware topology, it can be convenient to use the processor id (aka device name) as a proxy for the topology. Unfortunately, a given processor is not guaranteed to have a stable hardware topology. Indeed: rainbow
has grown from Sycamore23
to its current, larger configuration. For experimental record-keeping, it's important to have a fixed topology. Furthermore: to support comparisons between multiple processors with compatible hardware graphs (i.e. one is a subset-or-equal to another) it could be useful to have a "problem topology" decoupled from a hardware topology.
A simple "record keeping" approach would be to serialize the device graph for each problem. However, there is often considerable structure in these topologies (e.g. "this was a device graph" or "this is a line"). Additionally, for ReCirq's data collection idioms to be effective it is necessary to have a descriptive "hash" of all parameters (so they can be used as inputs, shared between dependent tasks, used as parts of the filename).
Therefore, I propose we have 1) a set of problem topology classes and 2) A name-to-topolgy mapping
SYC23_GRAPH = nx.from_edgelist([
((3, 2), (4, 2)), ((4, 1), (5, 1)), ((4, 2), (4, 1)),
((4, 2), (4, 3)), ((4, 2), (5, 2)), ((4, 3), (5, 3)),
((5, 1), (5, 0)), ((5, 1), (5, 2)), ((5, 1), (6, 1)),
((5, 2), (5, 3)), ((5, 2), (6, 2)), ((5, 3), (5, 4)),
((5, 3), (6, 3)), ((5, 4), (6, 4)), ((6, 1), (6, 2)),
((6, 2), (6, 3)), ((6, 2), (7, 2)), ((6, 3), (6, 4)),
((6, 3), (7, 3)), ((6, 4), (6, 5)), ((6, 4), (7, 4)),
((6, 5), (7, 5)), ((7, 2), (7, 3)), ((7, 3), (7, 4)),
((7, 3), (8, 3)), ((7, 4), (7, 5)), ((7, 4), (8, 4)),
((7, 5), (7, 6)), ((7, 5), (8, 5)), ((8, 3), (8, 4)),
((8, 4), (8, 5)), ((8, 4), (9, 4)),
])
class DeviceBasedTopology:
def __init__(self, graph, assoc_processor_id, epoch=1):
self.graph = graph
self.n_qubits = graph.number_of_nodes()
self.assoc_processor_id = assoc_processor_id
self.epoch = epoch
if epoch != 1:
epoch_str = f'-mk{epoch}'
else: epoch_str = ''
self.name = f'{assoc_processor_id}{epoch_str}'
RAINBOW_TOPOLOGY = DeviceBasedTopology(
graph=SYC23_GRAPH,
assoc_processor_id='rainbow',
epoch=1
)
Networkx subgraph isomorphism routines can be used to place compatible topologies