mindquantum.algorithm.nisq.chem.reference_state 源代码

# 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.
# ============================================================================

# Author : Xiaoxiao Xiao <xxxwwzi@163.com>
#          Zhendong Li <zhendongli@bnu.edu.cn>
# Affiliation: College of Chemistry, Beijing Normal University
# Publication: Xiao, X., Zhao, H., Ren, J., Fang, W. H., & Li, Z. (2023). arXiv:2307.03563.
"""Get a reference state preparation circuit."""
import sys
from typing import Iterable, Optional, Union

# pylint: disable=wrong-import-position
if sys.version_info < (3, 8):
    from typing_extensions import Literal, get_args
else:
    from typing import Literal, get_args

import numpy as np

from mindquantum.core.circuit import UN, Circuit
from mindquantum.core.gates import BarrierGate, H, X
from mindquantum.utils.type_value_check import (
    _check_input_type,
    _check_int_type,
    _check_value_should_not_less,
)

AVA_REF = Literal['HF', 'Neel', 'Bell', 'AllH']  # pylint: disable=invalid-name


# pylint: disable=too-many-branches
[文档]def get_reference_circuit( n_qubits: int, n_ele_alpha: Optional[int] = None, n_ele_beta: Optional[int] = None, ref: Union[AVA_REF, Iterable] = 'AllH', ): """ Get preparation circuit for reference circuit according to different methods. The available methods are: +--------+------------------------------------------------------------------------------+ | Method | Description | +========+==============================================================================+ | HF | Generate the Hartree-Fock (HF) reference state, where electrons occupy | | | the lowest energy orbitals, suitable for Hartree-Fock (HF) orbitals. | +--------+------------------------------------------------------------------------------+ | Neel | Generate the Neel reference state, where electrons with different spins | | | occupy adjacent orbitals, suitable for orthonormalized atomic orbitals. | +--------+------------------------------------------------------------------------------+ | Bell | Generate the tensor product of the Bell state as the reference state. | +--------+------------------------------------------------------------------------------+ | AllH | Generate the uniform superposition state as the reference state. | +--------+------------------------------------------------------------------------------+ Args: n_qubits (int): The total qubit number. n_ele_alpha (int): The number of alpha electrons. Default: ``None``. n_ele_beta (int): The number of beta electrons. Default: ``None``. ref (Union[str, Iterable]): The method to construct reference state. If it is a string, it should be one of ``'HF'``, ``'Neel'``, ``'Bell'``, ``'AllH'``. Otherwise, it should be a iterator of int, and we place a :class:`~.core.gates.RX` gate on each qubit. Default: ``'AllH'``. Examples: >>> from mindquantum.algorithm.nisq import get_reference_circuit >>> get_reference_circuit(4, 1, 1, 'HF') ┏━━━┓ q0: ──┨╺╋╸┠─▓─── ┗━━━┛ ▓ ┏━━━┓ ▓ q1: ──┨╺╋╸┠─▓─── ┗━━━┛ ▓ q2: ────────▓─── q3: ────────▓─── """ ava_ref = get_args(AVA_REF) _check_int_type('n_qubits', n_qubits) _check_value_should_not_less('n_qubits', 0, n_qubits) if n_ele_alpha is not None: _check_int_type('n_ele_alpha', n_ele_alpha) _check_value_should_not_less('n_ele_alpha', 0, n_ele_alpha) if n_ele_beta is not None: _check_int_type('n_ele_beta', n_ele_beta) _check_value_should_not_less('n_ele_beta', 0, n_ele_beta) full_barrier = Circuit() + BarrierGate().on(list(range(n_qubits))) if isinstance(ref, str): if ref not in ava_ref: raise ValueError(f'ref should be one of {ava_ref}, but get {ref}') if ref == 'HF': _check_input_type('n_ele_alpha', int, n_ele_alpha) _check_input_type('n_ele_beta', int, n_ele_beta) if n_ele_alpha + n_ele_beta > n_qubits: raise ValueError( f"Total electrons ({n_ele_alpha} + {n_ele_beta}) can not be greater than n_qubits ({n_qubits})" ) x_poi = np.arange(0, 2 * n_ele_alpha, 2).tolist() + np.arange(1, 2 * n_ele_beta + 1, 2).tolist() return UN(X, x_poi) + full_barrier if ref == 'Neel': _check_input_type('n_ele_alpha', int, n_ele_alpha) _check_input_type('n_ele_beta', int, n_ele_beta) if 2 * (n_ele_alpha + n_ele_beta) > n_qubits: raise ValueError( f"The position of the largest occupied qubit (2 * ({n_ele_alpha} + {n_ele_beta})" f" exceeds the total number of qubits ({n_qubits})." ) temp = [] if n_ele_alpha != 0: n_b = 0 for n_a in range(n_ele_alpha): temp += [1, 0] if n_b < n_ele_beta: temp += [0, 1] n_b += 1 else: n_a = 0 for n_b in range(n_ele_beta): temp += [1, 0] if n_a < n_ele_alpha: temp += [0, 1] n_a += 1 x_poi = [idx for idx, i in enumerate(temp) if i == 1] return UN(X, x_poi) + full_barrier if ref == 'Bell': even = (np.array(range(n_qubits // 2)) * 2).tolist() odd = (np.array(range(n_qubits // 2)) * 2 + 1).tolist() return UN(X, range(n_qubits)) + UN(H, even) + UN(X, odd, even) + full_barrier if ref == 'AllH': return UN(H, range(n_qubits)) + full_barrier return UN(X, ref) + full_barrier