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

Remaining pages of LRE user guide #2532

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions docs/source/guide/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pec.md
cdr.md
shadows.md
ddd.md
lre.md
rem.md
qse.md
pt.md
Expand Down
185 changes: 185 additions & 0 deletions docs/source/guide/lre-1-intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
---
jupytext:
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.11.1
kernelspec:
display_name: Python 3
language: python
name: python3
---


# How do I use LRE?


LRE works in two steps: generate noise-scaled circuits and apply inference to results from executed circuits.
Copy link
Contributor

Choose a reason for hiding this comment

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

Without additional comments on the layerwise aspect, this description could just as well apply to ZNE. While this description is not incorrect, it may be misleading as it could be applied to ZNE or LRE without further discussion on how the noise-scaling on different layers comes into the picture.



A user has the choice to either use {func}`.execute_with_lre` to combine both steps into one if they are
only interested in obtaining the mitigated expectation value or splitting the process into two using
{func}`.multivariate_layer_scaling` and {func}`.multivariate_richardson_coefficients`.


```{warning}
LRE is currently compatible with quantum programs written using `cirq`. Work on making this technique compatible with other frontends is ongoing. 🚧
```


## Problem Setup


To use {func}`.execute_with_lre` without any additional options the following are required:


- a quantum circuit
- a method of returning an expectation value from a circuit
- the degree of the multivariate polynomial extrapolation
- fold multiplier AKA the scaling gap which is used to generate the scale factor vectors


### Define the circuit of interest


For simplicity, we define a simple circuit whose ideal execution is identical to the identity operation.


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


circuit = benchmarks.generate_rb_circuits(n_qubits=1, num_cliffords=3)[0]


print(circuit)
```


### Define executor for ideal and noisy executions


We define an [executor](executors.md) which executes the input circuit subjected to depolarizing noise, and returns the probability of the ground state. By altering the value for `noise_level`, ideal and noisy expectation
values can be obtained.


```{code-cell} ipython3
import numpy as np
from cirq import DensityMatrixSimulator, depolarize


def execute(circuit, noise_level=0.025):
"""Default executor for all unit tests."""
noisy_circuit = circuit.with_noise(depolarize(p=noise_level))
rho = DensityMatrixSimulator().simulate(noisy_circuit).final_density_matrix
return rho[0, 0].real
```


Compare the noisy and ideal expectation values:


```{code-cell} ipython3
# Compute the expectation value of the |0><0| observable.
noisy_value = execute(circuit)
ideal_value = execute(circuit, noise_level=0.0)
print(f"Error without mitigation: {abs(ideal_value - noisy_value) :.5f}")
```


## Apply LRE directly


With the circuit, and executor defined, we just need to choose the polynomial extrapolation degree as well as the fold multiplier.
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove the first ,:

With the circuit and executor defined,



```{code-cell} ipython3
from mitiq.lre import execute_with_lre


input_degree = 2
input_fold_multiplier = 3


mitigated_result = execute_with_lre(
circuit,
execute,
degree = input_degree,
fold_multiplier = input_fold_multiplier,
)


print(f"Error with mitigation (ZNE): {abs(ideal_value - mitigated_result):.{3}}")
Copy link
Contributor

Choose a reason for hiding this comment

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

This print statement refers to ZNE but it should be LRE

```


## Step by step application of LRE

In this section we will walk through what happens in each of the two stages of LRE.


### Create noise-scaled circuits


We start with creating a number of noise-scaled circuits which we will pass to the executor.


```{code-cell} ipython3
from mitiq.lre import multivariate_layer_scaling


noise_scaled_circuits = multivariate_layer_scaling(circuit, input_degree, input_fold_multiplier)


print(f"total number of noise-scaled circuits for LRE = {len(noise_scaled_circuits)}")
```
An example noise-scaled circuit is shown below:


```{code-cell} ipython3
noise_scaled_circuits[3]
```


### Classical inference


Based on the choice of input parameters, a sample matrix created using {func}`.sample_matrix` is used to find the
coefficients of linear combination required for multivariate Richardson extrapolation (**link theory section here**).
Copy link
Contributor Author

Choose a reason for hiding this comment

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

To do: after #2522 is merged



```{code-cell} ipython3
from mitiq.lre import multivariate_richardson_coefficients

coeffs_of_linear_comb = multivariate_richardson_coefficients(
circuit,
fold_multiplier = input_fold_multiplier,
degree = input_degree,
)


print(f"total number of noise-scaled circuits for LRE = {len(noise_scaled_circuits)}")
print(f"total number of coefficients of linear combination for LRE = {len(coeffs_of_linear_comb)}")
```
Each noise scaled circuit has a coefficient of linear combination and a noisy expectation value associated with it.


### Combine the results


```{code-cell} ipython3
## execute each noise scaled circuit

noise_scaled_exp_values = []


for i in noise_scaled_circuits:
noise_scaled_exp_values.append(execute(i))


calculated_mitigated_result = np.dot(noise_scaled_exp_values, coeffs_of_linear_comb)
print(f"Error with mitigation (ZNE): {abs(ideal_value - calculated_mitigated_result):.{3}}")
Copy link
Contributor

Choose a reason for hiding this comment

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

Think ZNE should be LRE

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, thanks. Good catch!

```
The section [](lre-3-options.md) contains more information on other options available in LRE in addition to how to
control the hyperparameters associated with the LRE options.
46 changes: 46 additions & 0 deletions docs/source/guide/lre-2-use-case.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
jupytext:
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.10.3
kernelspec:
display_name: Python 3 (ipykernel)
language: python
name: python3
---


# When should I use LRE?


## Advantages


Layerwise Richardson Extrapolation is a generalized multivariate extension of the Richardson extrapolation where the univariate
version is available as an option in [ZNE](zne-3-options.md). Just as in ZNE, LRE can also be applied without a detailed knowledge of the underlying noise model as the effectiveness of the technique depends on the choice of scale factors. Thus, LRE is useful in scenarios where tomography is impractical.


The sampling overhead is flexible wherein the cost can be reduced by using larger values for the fold multiplier (used to
create the noise-scaled circuits) or by chunking a larger circuit into a smaller number of chunks.




## Disadvantages


When using a large circuit, the number of noise scaled circuits grows polynomially such that the execution time rises because we require the sample matrix to be a square matrix (**link theory page here**).
Copy link
Contributor Author

Choose a reason for hiding this comment

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

To do: after #2522 is merged



If one aims to reduce the sampling cost by using a larger fold multiplier, the bias for polynomial extrapolation increases as one moves farther away from the zero-noise limit.


Chunking a large circuit with a lower number of chunks to reduce the sampling cost can reduce the performance of LRE. In ZNE parlance, this is equivalent to local folding faring better than global folding in LRE when we use a higher number of chunks in [LRE](lre-3-options.md).
Copy link
Contributor

Choose a reason for hiding this comment

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

faring -> fairing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the phrase is supposed to be fare better not fair better.

https://dictionary.cambridge.org/us/dictionary/english/faring



```{note}
We are currently investigating the issue related to chunking large circuits, as reduced performance has been noticed in our testing.
```

15 changes: 15 additions & 0 deletions docs/source/guide/lre-3-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
jupytext:
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.11.1
kernelspec:
display_name: Python 3
language: python
name: python3
---

# What additional options are available when using LRE?

14 changes: 14 additions & 0 deletions docs/source/guide/lre-4-low-level.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
jupytext:
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.11.1
kernelspec:
display_name: Python 3
language: python
name: python3
---

# What happens when I use LRE?
12 changes: 12 additions & 0 deletions docs/source/guide/lre.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# LRE


```{toctree}
---
maxdepth: 1
---
lre-1-intro.md
lre-2-use-case.md
lre-3-options.md
lre-4-low-level.md
```