# Source code for mitiq.mitiq_qiskit.qiskit_utils

```
# Copyright (C) 2020 Unitary Fund
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
"""Qiskit utility functions."""
from typing import Optional
from qiskit import Aer, execute, QuantumCircuit
# Noise simulation packages
from qiskit.providers.aer.noise import NoiseModel
from qiskit.providers.aer.noise.errors.standard_errors import (
depolarizing_error,
)
from mitiq.benchmarks.randomized_benchmarking import rb_circuits
from mitiq.mitiq_qiskit.conversions import to_qiskit
BACKEND = Aer.get_backend("qasm_simulator")
[docs]def random_one_qubit_identity_circuit(num_cliffords: int) -> QuantumCircuit:
"""Returns a single-qubit identity circuit.
Args:
num_cliffords (int): Number of cliffords used to generate the circuit.
Returns:
circuit: Quantum circuit as a :class:`qiskit.QuantumCircuit` object.
"""
return to_qiskit(
rb_circuits(n_qubits=1, num_cliffords=[num_cliffords], trials=1)[0]
)
[docs]def run_with_noise(
circuit: QuantumCircuit,
noise: float,
shots: int,
seed: Optional[int] = None,
) -> float:
"""Runs the quantum circuit with a depolarizing channel noise model.
Args:
circuit: Ideal quantum circuit.
noise: Noise constant going into `depolarizing_error`.
shots: The Number of shots to run the circuit on the back-end.
seed: Optional seed for qiskit simulator.
Returns:
expval: expected values.
"""
# initialize a qiskit noise model
noise_model = NoiseModel()
# we assume a depolarizing error for each gate of the standard IBM basis
# set (u1, u2, u3)
noise_model.add_all_qubit_quantum_error(
depolarizing_error(noise, 1), ["u1", "u2", "u3"]
)
# execution of the experiment
job = execute(
circuit,
backend=BACKEND,
basis_gates=["u1", "u2", "u3"],
# we want all gates to be actually applied,
# so we skip any circuit optimization
optimization_level=0,
noise_model=noise_model,
shots=shots,
seed_simulator=seed,
)
results = job.result()
counts = results.get_counts()
expval = counts["0"] / shots
return expval
# For QISKIT the noise params are attributes of the simulation run and not of
# the program
# this means we need a stateful record of the scaled noise.
# Note this is NOT A GOOD SOLUTION IN THE LONG TERM AS HIDDEN STATE IS BAD
# Mainly this is qiskit's fault...
NATIVE_NOISE = 0.009
CURRENT_NOISE = None
[docs]def scale_noise(pq: QuantumCircuit, param: float) -> QuantumCircuit:
"""Scales the noise in a quantum circuit of the factor `param`.
Args:
pq: Quantum circuit.
noise: Noise constant going into `depolarizing_error`.
shots: Number of shots to run the circuit on the back-end.
Returns:
pq: quantum circuit as a :class:`qiskit.QuantumCircuit` object.
"""
global CURRENT_NOISE
noise = param * NATIVE_NOISE
assert noise <= 1.0, (
"Noise scaled to {} is out of bounds (<=1.0) for depolarizing "
"channel.".format(noise)
)
noise_model = NoiseModel()
# we assume a depolarizing error for each gate of the standard IBM basis
# set (u1, u2, u3)
noise_model.add_all_qubit_quantum_error(
depolarizing_error(noise, 1), ["u1", "u2", "u3"]
)
CURRENT_NOISE = noise_model
return pq
[docs]def run_program(
pq: QuantumCircuit, shots: int = 100, seed: Optional[int] = None
) -> float:
"""Runs a single-qubit circuit for multiple shots and
returns the expectation value of the ground state projector.
Args:
pq: Quantum circuit.
shots: Number of shots to run the circuit on the back-end.
seed: Optional seed for qiskit simulator.
Returns:
expval: expected value.
"""
job = execute(
pq,
backend=BACKEND,
basis_gates=["u1", "u2", "u3"],
# we want all gates to be actually applied,
# so we skip any circuit optimization
optimization_level=0,
noise_model=CURRENT_NOISE,
shots=shots,
seed_simulator=seed,
)
results = job.result()
counts = results.get_counts()
expval = counts["0"] / shots
return expval
```