Skip to content

Commit

Permalink
Quantum Volume: Add the ability to specify the device graph to compil…
Browse files Browse the repository at this point in the history
…e the model circuit onto (#2645)

This should give us the ability to try different parts of the device to find the optimal configuration. Note that the qubits that were used are already returned in the QuantumVolumeResult.compiled_circuit property.

@mpharrigan
  • Loading branch information
KevinVillela authored and CirqBot committed Dec 17, 2019
1 parent 7fb1a49 commit 2c8914b
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 24 deletions.
32 changes: 21 additions & 11 deletions cirq/contrib/quantum_volume/quantum_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
https://arxiv.org/abs/1811.12926.
"""

from typing import Optional, List, cast, Callable, Dict, Tuple, Set
from typing import Optional, List, cast, Callable, Dict, Tuple, Set, Union
from dataclasses import dataclass

import numpy as np
import pandas as pd
import networkx as nx

import cirq
import cirq.contrib.routing as ccr
Expand Down Expand Up @@ -219,14 +220,14 @@ def optimization_at(self, circuit: cirq.Circuit, index: int,
def compile_circuit(
circuit: cirq.Circuit,
*,
device: cirq.google.XmonDevice,
device_graph: nx.Graph,
routing_attempts: int,
compiler: Callable[[cirq.Circuit], cirq.Circuit] = None,
routing_algo_name: Optional[str] = None,
router: Optional[Callable[..., ccr.SwapNetwork]] = None,
add_readout_error_correction=False,
) -> CompilationResult:
"""Compile the given model circuit onto the given device. This uses a
"""Compile the given model circuit onto the given device graph. This uses a
different compilation method than described in
https://arxiv.org/pdf/1811.12926.pdf Appendix A. The latter goes through a
7-step process involving various decompositions, routing, and optimization
Expand All @@ -235,7 +236,7 @@ def compile_circuit(
Args:
circuit: The model circuit to compile.
device: The device to compile onto.
device_graph: The device graph to compile onto.
routing_attempts: See doc for calculate_quantum_volume.
compiler: An optional function to deconstruct the model circuit's
gates down to the target devices gate set and then optimize it.
Expand Down Expand Up @@ -278,7 +279,7 @@ def compile_circuit(
swap_networks: List[ccr.SwapNetwork] = []
for _ in range(routing_attempts):
swap_network = ccr.route_circuit(compiled_circuit,
ccr.xmon_device_to_graph(device),
device_graph,
router=router,
algo_name=routing_algo_name)
swap_networks.append(swap_network)
Expand Down Expand Up @@ -365,7 +366,7 @@ def prepare_circuits(

def execute_circuits(
*,
device: cirq.google.XmonDevice,
device_graph: nx.Graph,
samplers: List[cirq.Sampler],
circuits: List[Tuple[cirq.Circuit, List[int]]],
routing_attempts: int,
Expand All @@ -376,7 +377,7 @@ def execute_circuits(
"""Executes the given circuits on the given samplers.
Args
device: The device to run the compiled circuit on.
device_graph: The device graph to run the compiled circuit on.
samplers: The samplers to run the algorithm on.
circuits: The circuits to sample from.
routing_attempts: See doc for calculate_quantum_volume.
Expand All @@ -399,7 +400,7 @@ def execute_circuits(
compiled_circuits.append(
compile_circuit(
model_circuit,
device=device,
device_graph=device_graph,
compiler=compiler,
routing_attempts=routing_attempts,
add_readout_error_correction=add_readout_error_correction))
Expand Down Expand Up @@ -429,7 +430,7 @@ def calculate_quantum_volume(
num_qubits: int,
depth: int,
num_circuits: int,
device: cirq.google.XmonDevice,
device_or_qubits: Union[cirq.google.XmonDevice, List[cirq.GridQubit]],
samplers: List[cirq.Sampler],
random_state: cirq.value.RANDOM_STATE_LIKE = None,
compiler: Callable[[cirq.Circuit], cirq.Circuit] = None,
Expand All @@ -451,7 +452,8 @@ def calculate_quantum_volume(
depth: The number of gate layers to generate.
num_circuits: The number of random circuits to run.
random_state: Random state or random state seed.
device: The device to run the compiled circuit on.
device_or_qubits: The device or the device qubits to run the compiled
circuit on.
samplers: The samplers to run the algorithm on.
compiler: An optional function to compiler the model circuit's
gates down to the target devices gate set and the optimize it.
Expand All @@ -474,9 +476,17 @@ def calculate_quantum_volume(
depth=depth,
num_circuits=num_circuits,
random_state=random_state)

# Get the device graph from the given qubits or device.
device_graph = None
if isinstance(device_or_qubits, list):
device_graph = ccr.gridqubits_to_graph_device(device_or_qubits)
else:
device_graph = ccr.xmon_device_to_graph(device_or_qubits)

return execute_circuits(
circuits=circuits,
device=device,
device_graph=device_graph,
compiler=compiler,
samplers=samplers,
repetitions=repetitions,
Expand Down
47 changes: 35 additions & 12 deletions cirq/contrib/quantum_volume/quantum_volume_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,11 @@ def test_sample_heavy_set_with_parity():
def test_compile_circuit_router():
"""Tests that the given router is used."""
router_mock = MagicMock()
cirq.contrib.quantum_volume.compile_circuit(cirq.Circuit(),
device=cirq.google.Bristlecone,
router=router_mock,
routing_attempts=1)
cirq.contrib.quantum_volume.compile_circuit(
cirq.Circuit(),
device_graph=ccr.xmon_device_to_graph(cirq.google.Bristlecone),
router=router_mock,
routing_attempts=1)
router_mock.assert_called()


Expand All @@ -132,7 +133,7 @@ def test_compile_circuit():
])
compilation_result = cirq.contrib.quantum_volume.compile_circuit(
model_circuit,
device=cirq.google.Bristlecone,
device_graph=ccr.xmon_device_to_graph(cirq.google.Bristlecone),
compiler=compiler_mock,
routing_attempts=1)

Expand All @@ -156,7 +157,7 @@ def test_compile_circuit_replaces_swaps():
])
compilation_result = cirq.contrib.quantum_volume.compile_circuit(
model_circuit,
device=cirq.google.Bristlecone,
device_graph=ccr.xmon_device_to_graph(cirq.google.Bristlecone),
compiler=compiler_mock,
routing_attempts=1)

Expand Down Expand Up @@ -186,7 +187,7 @@ def test_compile_circuit_with_readout_correction():
])
compilation_result = cirq.contrib.quantum_volume.compile_circuit(
model_circuit,
device=cirq.google.Bristlecone,
device_graph=ccr.xmon_device_to_graph(cirq.google.Bristlecone),
compiler=compiler_mock,
router=router_mock,
routing_attempts=1,
Expand Down Expand Up @@ -226,7 +227,7 @@ def test_compile_circuit_multiple_routing_attempts():

compilation_result = cirq.contrib.quantum_volume.compile_circuit(
model_circuit,
device=cirq.google.Bristlecone,
device_graph=ccr.xmon_device_to_graph(cirq.google.Bristlecone),
compiler=compiler_mock,
router=router_mock,
routing_attempts=3)
Expand All @@ -245,7 +246,9 @@ def test_compile_circuit_no_routing_attempts():

with pytest.raises(AssertionError) as e:
cirq.contrib.quantum_volume.compile_circuit(
model_circuit, device=cirq.google.Bristlecone, routing_attempts=0)
model_circuit,
device_graph=ccr.xmon_device_to_graph(cirq.google.Bristlecone),
routing_attempts=0)
assert e.match('Unable to get routing for circuit')


Expand All @@ -255,7 +258,7 @@ def test_calculate_quantum_volume_result():
num_qubits=3,
depth=3,
num_circuits=1,
device=cirq.google.Bristlecone,
device_or_qubits=cirq.google.Bristlecone,
samplers=[cirq.Simulator()],
routing_attempts=2,
random_state=1,
Expand All @@ -273,6 +276,26 @@ def test_calculate_quantum_volume_result():
cirq.to_json(results, buffer)


def test_calculate_quantum_volume_result_with_device_graph():
"""Test that running the main loop routes the circuit onto the given device
graph"""
device_qubits = [cirq.GridQubit(i, j) for i in range(2) for j in range(3)]
results = cirq.contrib.quantum_volume.calculate_quantum_volume(
num_qubits=3,
depth=3,
num_circuits=1,
device_or_qubits=device_qubits,
samplers=[cirq.Simulator()],
routing_attempts=2,
random_state=1,
)

assert len(results) == 1
assert ccr.ops_are_consistent_with_device_graph(
results[0].compiled_circuit.all_operations(),
ccr.get_grid_device_graph(2, 3))


def test_calculate_quantum_volume_loop():
"""Test that calculate_quantum_volume is able to run without erring."""
# Keep test from taking a long time by lowering circuits and routing
Expand All @@ -283,7 +306,7 @@ def test_calculate_quantum_volume_loop():
num_circuits=1,
routing_attempts=2,
random_state=1,
device=cirq.google.Bristlecone,
device_or_qubits=cirq.google.Bristlecone,
samplers=[cirq.Simulator()])


Expand All @@ -298,6 +321,6 @@ def test_calculate_quantum_volume_loop_with_readout_correction():
num_circuits=1,
routing_attempts=2,
random_state=1,
device=cirq.google.Bristlecone,
device_or_qubits=cirq.google.Bristlecone,
samplers=[cirq.Simulator()],
add_readout_error_correction=True)
2 changes: 1 addition & 1 deletion examples/advanced/quantum_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def main(*, num_qubits: int, depth: int, num_circuits: int, seed: int):
depth=depth,
num_circuits=num_circuits,
random_state=seed,
device=device,
device_or_qubits=device,
samplers=[cirq.Simulator(), noisy],
compiler=compiler)

Expand Down

0 comments on commit 2c8914b

Please sign in to comment.