Source code for mindquantum.algorithm.error_mitigation.random_benchmarking

# Copyright 2023 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ============================================================================
"""randomized benchmarking module."""
# pylint:disable=no-member
import numpy as np

from mindquantum import _mq_vector
from mindquantum.core.circuit import Circuit
from mindquantum.simulator import Simulator, decompose_stabilizer
from mindquantum.simulator.stabilizer import Stabilizer
from mindquantum.utils.type_value_check import (
    _check_int_type,
    _check_seed,
    _check_value_should_not_less,
)


[docs]def query_single_qubit_clifford_elem(idx: int) -> Simulator: """ Query a element of single qubit clifford group. The size of single qubit clifford group is 24. Args: idx (int): The index of clifford element in single qubit clifford group. Returns: :class:`~.simulator.Simulator`, a stabilizer with tableau be the queried clifford element. Examples: >>> from mindquantum.algorithm.error_mitigation import query_single_qubit_clifford_elem >>> from mindquantum.simulator import decompose_stabilizer >>> elem = query_single_qubit_clifford_elem(12) >>> decompose_stabilizer(elem) ┏━━━┓ ┏━━━┓ ┏━━━━┓ q0: ──┨╺╋╸┠─┨ H ┠─┨ S† ┠─── ┗━━━┛ ┗━━━┛ ┗━━━━┛ """ _check_int_type('idx', idx) _check_value_should_not_less("idx", 0, idx) clifford = Stabilizer(_mq_vector.stabilizer.query_single_qubit_clifford_elem(idx), n_qubits=1, internal=True) sim = Simulator('stabilizer', 1) sim.backend = clifford return sim
[docs]def query_double_qubits_clifford_elem(idx: int) -> Simulator: """ Query a element of double qubits clifford group. The size of double qubits clifford group is 11520. Args: idx (int): The index of clifford element in double qubits clifford group. Returns: :class:`~.simulator.Simulator`, a stabilizer with tableau be the queried clifford element. Examples: >>> from mindquantum.algorithm.error_mitigation import query_double_qubits_clifford_elem >>> from mindquantum.simulator import decompose_stabilizer >>> elem = query_double_qubits_clifford_elem(11111) >>> decompose_stabilizer(elem) ┏━━━┓ ┏━━━━┓ ┏━━━┓ ┏━━━┓ q0: ──┨╺╋╸┠─┨ S† ┠───────┨╺╋╸┠───■───┨╺╋╸┠─── ┗━━━┛ ┗━━━━┛ ┗━┳━┛ ┃ ┗━┳━┛ ┏━━━┓ ┏━━━━┓ ┏━━━┓ ┃ ┏━┻━┓ ┃ q1: ──┨ H ┠─┨ S† ┠─┨ H ┠───■───┨╺╋╸┠───■───── ┗━━━┛ ┗━━━━┛ ┗━━━┛ ┗━━━┛ """ _check_int_type('idx', idx) _check_value_should_not_less("idx", 0, idx) clifford = Stabilizer(_mq_vector.stabilizer.query_double_qubits_clifford_elem(idx), n_qubits=2, internal=True) sim = Simulator('stabilizer', 2) sim.backend = clifford return sim
[docs]def generate_single_qubit_rb_circ(length: int, seed: int = None) -> Circuit: """ Generate a single qubit randomized benchmarking circuit. Args: length (int): The length of total clifford elements. seed (int): The random seed to generate benchmarking circuit. If ``None``, a random seed will be used. Default: ``None``. Returns: :class:`~.core.circuit.Circuit`, the single qubit randomized benchmarking circuit, the quantum state of this circuit is zero state. Examples: >>> import numpy as np >>> from mindquantum.algorithm.error_mitigation import generate_single_qubit_rb_circ >>> circ = generate_single_qubit_rb_circ(5, 42) >>> circ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ q0: ──┨ S ┠─┨ Z ┠─▓─┨ H ┠─▓─┨ H ┠─┨ S ┠─┨ H ┠─┨ Z ┠─┨╺╋╸┠─▓─┨ S ┠─┨ H ┠─↯─ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ q0: ──┨ S ┠─┨ H ┠─┨ Z ┠─┨╺╋╸┠─▓─┨ S ┠─┨ Z ┠─▓─── ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ >>> np.abs(circ.get_qs()) array([1., 0.]) """ _check_int_type('length', length) _check_value_should_not_less('length', 0, length) if seed is None: seed = int(np.random.randint(1, 2 << 20)) _check_seed(seed) stabs = _mq_vector.stabilizer.generate_single_qubit_rb_circ(length, seed) circ = Circuit() for stab in stabs: circ.barrier() circ += decompose_stabilizer(Stabilizer(stab, n_qubits=1, internal=True)) return circ.hermitian()
[docs]def generate_double_qubits_rb_circ(length: int, seed: int = None) -> Circuit: """ Generate a double qubits randomized benchmarking circuit. Args: length (int): The length of total clifford elements. seed (int): The random seed to generate benchmarking circuit. If ``None``, a random seed will be used. Default: ``None``. Returns: :class:`~.core.circuit.Circuit`, the double qubit randomized benchmarking circuit, the quantum state of this circuit is zero state. Examples: >>> import numpy as np >>> from mindquantum.algorithm.error_mitigation import generate_double_qubits_rb_circ >>> circ = generate_double_qubits_rb_circ(3, 42) >>> circ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ q0: ──┨╺╋╸┠─┨ S ┠─┨╺╋╸┠─┨ H ┠─┨ S ┠─┨ H ┠─┨ Z ┠─┨╺╋╸┠─▓───■───┨╺╋╸┠─┨ H ┠─↯─ ┗━┳━┛ ┗━━━┛ ┗━┳━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ▓ ┃ ┗━┳━┛ ┗━━━┛ ┃ ┃ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ▓ ┏━┻━┓ ┃ q1: ────■───────────■───┨ S ┠─┨ H ┠─┨ Z ┠─┨╺╋╸┠───────▓─┨╺╋╸┠───■─────────↯─ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ q0: ────■───┨ H ┠─────────────────────────▓─┨╺╋╸┠───■───┨ S ┠─┨ H ┠───■───↯─ ┃ ┗━━━┛ ▓ ┗━┳━┛ ┃ ┗━━━┛ ┗━━━┛ ┃ ┏━┻━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ▓ ┃ ┏━┻━┓ ┏━┻━┓ q1: ──┨╺╋╸┠─┨ H ┠─┨ S ┠─┨ H ┠─┨ Z ┠─┨╺╋╸┠─▓───■───┨╺╋╸┠─────────────┨╺╋╸┠─↯─ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┏━━━┓ ┏━━━┓ q0: ──┨ H ┠─┨ Z ┠───────────────────▓─── ┗━━━┛ ┗━━━┛ ▓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ▓ q1: ──┨ S ┠─┨ H ┠─┨ S ┠─┨ H ┠─┨ Z ┠─▓─── ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ >>> np.abs(circ.get_qs()) array([1., 0., 0., 0.]) """ _check_int_type('length', length) _check_value_should_not_less('length', 0, length) if seed is None: seed = int(np.random.randint(1, 2 << 20)) _check_seed(seed) stabs = _mq_vector.stabilizer.generate_double_qubits_rb_circ(length, seed) circ = Circuit() for stab in stabs: circ.barrier() circ += decompose_stabilizer(Stabilizer(stab, n_qubits=2, internal=True)) return circ.hermitian()