-
-
Notifications
You must be signed in to change notification settings - Fork 166
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
main functions without corrected mypy errors, unit tests and docstrings
- Loading branch information
1 parent
1a3705c
commit 6614641
Showing
4 changed files
with
150 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# Copyright (C) Unitary Fund | ||
# | ||
# This source code is licensed under the GPL license (v3) found in the | ||
# LICENSE file in the root directory of this source tree. | ||
|
||
"""Extrapolation methods for Layerwise Richardson Extrapolation (LRE)""" | ||
|
||
from functools import wraps | ||
from typing import Callable, Optional, Union | ||
|
||
import numpy as np | ||
from cirq import Circuit | ||
|
||
from mitiq import Executor, Observable, QuantumResult | ||
from mitiq.lre import ( | ||
multivariate_layer_scaling, | ||
multivariate_richardson_coefficients, | ||
) | ||
from mitiq.zne.scaling import fold_gates_at_random | ||
|
||
|
||
def execute_with_lre( | ||
input_circuit: Circuit, | ||
executor: Union[Executor, Callable[[Circuit], QuantumResult]], | ||
shots: int, | ||
degree: int, | ||
fold_multiplier: int, | ||
folding_method: Callable[[Circuit, float], Circuit] = fold_gates_at_random, | ||
num_chunks: Optional[int] = None, | ||
observable: Optional[Observable] = None, | ||
)-> float: | ||
noise_scaled_circuits = multivariate_layer_scaling( | ||
input_circuit, degree, fold_multiplier, num_chunks, folding_method | ||
) | ||
linear_combination_coeffs = multivariate_richardson_coefficients( | ||
input_circuit, degree, fold_multiplier, num_chunks | ||
) | ||
normalized_shots_list = shots // len(linear_combination_coeffs) | ||
rescaled_shots_list = [normalized_shots_list] * len( | ||
linear_combination_coeffs | ||
) | ||
|
||
lre_exp_values = [] | ||
for circuit_shots, scaled_circuit in zip( | ||
rescaled_shots_list, noise_scaled_circuits | ||
): | ||
circ_exp_val = executor(scaled_circuit, shots=circuit_shots) | ||
lre_exp_values.append(circ_exp_val) | ||
|
||
# verify the linear combination coefficients and the calculated expectation | ||
# values have the same length | ||
assert len(lre_exp_values) == len(linear_combination_coeffs) | ||
|
||
return np.dot(lre_exp_values, linear_combination_coeffs) | ||
|
||
|
||
def mitigate_executor( | ||
executor: Union[Executor, Callable[[Circuit], QuantumResult]], | ||
shots: int, | ||
degree: int, | ||
fold_multiplier: int, | ||
folding_method: Callable[[Circuit, float], Circuit] = fold_gates_at_random, | ||
num_chunks: Optional[int] = None, | ||
observable: Optional[Observable] = None, | ||
) -> Callable[[Circuit], float]: | ||
@wraps(executor) | ||
def new_executor(input_circuit: Circuit) -> float: | ||
return execute_with_lre( | ||
input_circuit, | ||
executor, | ||
shots, | ||
degree, | ||
fold_multiplier, | ||
folding_method, | ||
num_chunks, | ||
observable, | ||
) | ||
|
||
return new_executor | ||
|
||
|
||
def lre_decorator( | ||
shots: int, | ||
degree: int, | ||
fold_multiplier: int, | ||
folding_method: Callable[[Circuit, float], Circuit] = fold_gates_at_random, | ||
num_chunks: Optional[int] = None, | ||
observable: Optional[Observable] = None, | ||
) -> Callable[ | ||
[Callable[[Circuit], QuantumResult]], Callable[[Circuit], float] | ||
]: | ||
# Raise an error if the decorator is used without parenthesis | ||
if callable(observable): | ||
raise TypeError( | ||
"Decorator must be used with parentheses (i.e., @lre_decorator()) " | ||
"with explicit arguments for shots, degree and fold_multiplier." | ||
) | ||
|
||
def decorator( | ||
executor: Callable[[Circuit], QuantumResult], | ||
) -> Callable[[Circuit], float]: | ||
return mitigate_executor( | ||
executor, | ||
shots, | ||
degree, | ||
fold_multiplier, | ||
folding_method, | ||
num_chunks, | ||
observable, | ||
) | ||
|
||
return decorator | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
"""Unit tests for the LRE extrapolation methods.""" | ||
|
||
from cirq import DensityMatrixSimulator, depolarize | ||
|
||
from mitiq import benchmarks | ||
from mitiq.lre import execute_with_lre | ||
|
||
test_cirq = benchmarks.generate_rb_circuits( | ||
n_qubits=1, | ||
num_cliffords=2, | ||
)[0] | ||
|
||
|
||
def execute(circuit, noise_level=0.025, shots=1000): | ||
"""Returns Tr[ρ |0⟩⟨0|] where ρ is the state prepared by the circuit | ||
executed with depolarizing noise. | ||
""" | ||
# Replace with code based on your frontend and backend. | ||
mitiq_circuit = circuit | ||
noisy_circuit = mitiq_circuit.with_noise(depolarize(p=noise_level)) | ||
rho = DensityMatrixSimulator().simulate(noisy_circuit).final_density_matrix | ||
return rho[0, 0].real | ||
|
||
|
||
def test_lre_exp_value(): | ||
noisy_val = execute(test_cirq) | ||
ideal_val = execute(test_cirq, noise_level=0, shots=1000) | ||
assert abs(ideal_val - noisy_val) > 0 | ||
lre_exp_val = execute_with_lre(test_cirq, execute, 1000, 2, 2) | ||
assert lre_exp_val > noisy_val |