Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2274 Benchmark User Guide #2566

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
eedd305
adding benchmark user guide
Shivansh20128 Nov 11, 2024
215ecf6
adding benchmark circuit names
Shivansh20128 Nov 12, 2024
e7c3a3b
adding content for ghz
Shivansh20128 Nov 12, 2024
99b6848
updated changes
Shivansh20128 Nov 12, 2024
3648c29
updating example
Shivansh20128 Nov 12, 2024
63da003
adding examples to doc
Shivansh20128 Nov 13, 2024
f6876c2
adding documentation for benchmark circuits
Shivansh20128 Nov 13, 2024
d8b9232
Update docs/source/guide/benchmarks.md
Shivansh20128 Nov 13, 2024
f6a1ed8
Update docs/source/guide/benchmarks.md
Shivansh20128 Nov 13, 2024
07e298b
Update docs/source/guide/benchmarks.md
Shivansh20128 Nov 13, 2024
f1b36bb
Update docs/source/guide/benchmarks.md
Shivansh20128 Nov 13, 2024
ccb5586
Update docs/source/guide/benchmarks.md
Shivansh20128 Nov 13, 2024
e94ae2e
Update docs/source/guide/benchmarks.md
Shivansh20128 Nov 13, 2024
0a90ac5
Update docs/source/guide/benchmarks.md
Shivansh20128 Nov 13, 2024
e5e6746
Update docs/source/guide/benchmarks.md
Shivansh20128 Nov 13, 2024
0a17fb6
Update docs/source/guide/benchmarks.md
Shivansh20128 Nov 13, 2024
f9bca24
suggestions added
Shivansh20128 Nov 13, 2024
030a819
Merge branch 'unitaryfund:main' into 2274-benchmark-user-guide
Shivansh20128 Nov 13, 2024
8e07d13
changing circuit size in examples
Shivansh20128 Nov 14, 2024
d3dcfab
Merge branch '2274-benchmark-user-guide' of https://github.com/Shivan…
Shivansh20128 Nov 14, 2024
e03961a
adding ideal state of circuits
Shivansh20128 Nov 15, 2024
302eea0
adding mirror circuits example
Shivansh20128 Nov 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 194 additions & 0 deletions docs/source/guide/benchmarks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
---
jupytext:
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.11.4
kernelspec:
display_name: Python 3
language: python
name: python3
---

# Benchmarks

Mitiq benchmarks error mitigation techniques by running quantum circuits with and without mitigation, measuring improvements in accuracy, fidelity, and error rates. The process involves executing various circuit types—like GHZ, Mirror, Quantum Volume, and Randomized Benchmarking circuits—and comparing mitigated results against ideal outcomes. Analysis of these benchmarking results produces performance metrics, comparing mitigated and unmitigated outputs to quantify error reduction. This helps assess Mitiq’s effectiveness across diverse circuits, highlighting strengths and limitations in noise reduction.

The benchmark circuits can be used using the following workflow.

```{code-cell} ipython3
purva-thakre marked this conversation as resolved.
Show resolved Hide resolved
import cirq
from mitiq import benchmarks, zne

def execute(circuit, noise_level=0.005):
"""Returns Tr[ρ |0⟩⟨0|] where ρ is the state prepared by the circuit
with depolarizing noise."""
noisy_circuit = circuit.with_noise(cirq.depolarize(p=noise_level))
return (
cirq.DensityMatrixSimulator()
.simulate(noisy_circuit)
.final_density_matrix[0, 0]
.real
)

circuit = benchmarks.generate_ghz_circuit(n_qubits=7) # Call the required benchmark circuit function here
print(circuit.final_state_vector()) # Shows the ideal circuit state

true_value = execute(circuit, noise_level=0.0) # Ideal quantum computer
noisy_value = execute(circuit) # Noisy quantum computer
zne_value = zne.execute_with_zne(circuit, execute) # Noisy quantum computer + Mitiq

print(f"Error w/o Mitiq: {abs((true_value - noisy_value) / true_value):.3f}")
print(f"Error w Mitiq: {abs((true_value - zne_value) / true_value):.3f}")
```


## GHZ Circuits

The {func}`.generate_ghz_circuit` create the GHZ states that are highly sensitive to noise. Thus, they make it easy to test error rates in entanglement creation and preservation, which is central for many quantum algorithms.

```{code-cell} ipython3
from mitiq.benchmarks import generate_ghz_circuit

circuit = generate_ghz_circuit(n_qubits=7)
print(circuit)
```

## Mirror Circuits

The {func}`.generate_mirror_circuit` involves running a quantum circuit forward and then “mirroring” it (applying the reverse operations). Ideally, this results in returning the system to the initial state, so they’re great for testing if the noise mitigation is effective in preserving information through complex sequences.

```{code-cell} ipython3
from typing import List, Tuple
import numpy as np
import cirq
import networkx as nx
from mitiq import zne
from mitiq import benchmarks

topology = nx.complete_graph(3)

def get_circuit(depth: int) -> Tuple[cirq.Circuit, List[int]]:
circuit, correct_bitstring = benchmarks.generate_mirror_circuit(
nlayers=depth,
two_qubit_gate_prob=1.0,
connectivity_graph=topology,
return_type="cirq",
)
return circuit, correct_bitstring

circuit, correct_bitstring = get_circuit(depth=3)

def execute(
circuit: cirq.Circuit,
correct_bitstring: List[int],
noise_level=0.005,
) -> float:
"""Executes the input circuit(s) and returns ⟨A⟩, where
A = |correct_bitstring⟩⟨correct_bitstring| for each circuit.
"""
noisy_circuit = circuit.with_noise(cirq.depolarize(p=noise_level))

noisy_circuit += cirq.measure(*sorted(circuit.all_qubits()), key="m")
backend = cirq.DensityMatrixSimulator()

backend = cirq.DensityMatrixSimulator()

result = backend.run(noisy_circuit)
expval = result.measurements["m"].tolist().count(correct_bitstring)
return expval

def execute_with_fixed_bitstring(circuit, noise_level=0.005):
return execute(circuit, correct_bitstring, noise_level)

print(circuit)
print(circuit.final_state_vector()) # Shows the ideal circuit state

true_value = execute(circuit, correct_bitstring,noise_level=0.0)
noisy_value = execute(circuit, correct_bitstring)

zne_value = zne.execute_with_zne(circuit, execute_with_fixed_bitstring) # Noisy quantum computer + Mitiq

print(f"Error w/o Mitiq: {abs((true_value - noisy_value) / true_value):.3f}")
print(f"Error w Mitiq: {abs((true_value - zne_value) / true_value):.3f}")
```

## Mirror Quantum Volume Circuits

The {func}`.generate_mirror_qv_circuit` is designed to test `quantum volume`, a metric combining circuit depth, number of qubits, and fidelity. These circuits check whether error mitigation techniques help achieve higher effective quantum volumes on noisy devices.

```{code-cell} ipython3
from mitiq.benchmarks import generate_mirror_qv_circuit

circuit= generate_mirror_qv_circuit(num_qubits=7, depth=2)
print(circuit)
```

## Quantum Phase Estimation Circuits

The {func}`.generate_qpe_circuit` is used to the measure eigenvalues of unitary operators. Since accurate phase estimation requires precise control over operations, these circuits test the mitigation techniques’ ability to handle small noise effects over multiple gate sequences.

```{code-cell} ipython3
from mitiq.benchmarks import generate_w_circuit

circuit = generate_w_circuit(n_qubits=7)
print(circuit)
```

## Quantum Volume Circuits

The {func}`.generate_quantum_volume_circuit` tests the maximum achievable "volume" or computational capacity of a quantum processor. Running these circuits with error mitigation tests if mitiq’s techniques improve the effective quantum volume.

```{code-cell} ipython3
from mitiq.benchmarks import generate_quantum_volume_circuit

circuit,_ = generate_quantum_volume_circuit(num_qubits=4, depth=7)
print(circuit)
```

## Randomized Benchmarking Circuits

The {func}`.generate_rb_circuits` are sequences of random gates (generally Clifford gates), to estimate an average error rate. They’re standard in benchmarking for evaluating how well mitiq’s error mitigation reduces this error rate across different levels of noise.
Copy link
Collaborator

@purva-thakre purva-thakre Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add some details about what the state of each circuit is supposed to be? For example, the ideal output of a randomized benchmarking circuit is an identity.

GHZ and W circuits define a state. So, you could use some latex equations to show what the states are supposed to be etc.

We don't want to describe what the addition of noise will do to a circuit. the focus is on the details of the benchmarking circuit. All docstrings link a reference used to define a particular benchmarking circuit. You could use details from these refs if you don't know a lot about these circuits.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also use .final_state_vector() to show the ideal circuit state, which is what we expect it to be.

from mitiq.benchmarks import generate_ghz_circuit
circuit = generate_ghz_circuit(n_qubits=3)
circuit.final_state_vector()

this will spit out the 1-D vector form of a 3 qubit GHZ state.

image

Copy link
Author

@Shivansh20128 Shivansh20128 Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also use .final_state_vector() to show the ideal circuit state, which is what we expect it to be.

Yes, I can add this function to the example workflow at the top of the file instead of adding it explicitly inside every circuit, so every circuit's ideal circuit state can be seen.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to describe what the addition of noise will do to a circuit. the focus is on the details of the benchmarking circuit. All docstrings link a reference used to define a particular benchmarking circuit. You could use details from these refs if you don't know a lot about these circuits.

Since the section is about benchmarking, I believe we should show improvements with mitiq when compared to a noisy circuit without mitiq. But if you think otherwise, I can remove that part from the examples.

Also, since I have now added .final_state_vector(), shall I still go ahead and add the latex equations to show what the states are supposed to be?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The focus is on benchmarking circuits. Not benchmarking the performance of a QEM technique using mitiq.


```{code-cell} ipython3
from mitiq.benchmarks import generate_rb_circuits

circuits = generate_rb_circuits(n_qubits=1, num_cliffords=5)
circuit=circuits[0]
print(circuit)
```

## Rotated Randomized Benchmarking Circuits

The {func}`.generate_rotated_rb_circuits` are sequences of random gates similar to {func}`.generate_rb_circuits`, but with rotations added, that allows assessment of errors beyond just the standard Clifford gates. They’re useful to check how well Mitiq handles noise in scenarios with more diverse gates.

```{code-cell} ipython3
from mitiq.benchmarks import generate_rotated_rb_circuits

circuits = generate_rotated_rb_circuits(n_qubits=1, num_cliffords=5)
circuit=circuits[0]
print(circuit)
```

## Randomized Clifford+T Circuits

The {func}`.generate_random_clifford_t_circuit` add the T gate to the standard Clifford set, adding more complex operations to the random benchmarking. This type evaluates Mitiq’s performance with gate sets that go beyond the Clifford gates, crucial for fault-tolerant computing.

```{code-cell} ipython3
from mitiq.benchmarks import generate_random_clifford_t_circuit

circuit = generate_random_clifford_t_circuit(num_qubits=7, num_oneq_cliffords=2, num_twoq_cliffords=2, num_t_gates=2)
print(circuit)
```

## W State Circuits

The {func}`.generate_w_circuit` are entangled circuits that distribute the entanglement across qubits differently than GHZ states. Testing with W state circuits can help explore how well a device maintains distributed entanglement in noisy environments.

```{code-cell} ipython3
from mitiq.benchmarks import generate_w_circuit

circuit = generate_w_circuit(n_qubits=7)
print(circuit)
```
1 change: 1 addition & 0 deletions docs/source/guide/core-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ frontends-backends.md
executors.md
observables.md
calibrators.md
benchmarks.md
```