mindquantum.algorithm.nisq.qnn.iqp_encoding 源代码

# Copyright 2021 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.
# ============================================================================
"""General IQP Encoding."""

import numpy as np

from mindquantum.algorithm.nisq._ansatz import Ansatz
from mindquantum.core.circuit import UN, Circuit
from mindquantum.core.gates import BARRIER, RZ, H, ParameterGate, X
from mindquantum.utils.type_value_check import (
    _check_input_type,
    _check_int_type,
    _check_value_should_not_less,
)


def _check_intrinsconeparagate(msg, gate_type):
    if not issubclass(gate_type, ParameterGate):
        raise TypeError(f"{msg} requires a type of {ParameterGate}, but get {gate_type}")


[文档]class IQPEncoding(Ansatz): """ General IQP Encoding. For more information, please refer to `Supervised learning with quantum-enhanced feature spaces <https://www.nature.com/articles/s41586-019-0980-2>`_. Args: n_feature (int): The number of feature of data you want to encode with IQPEncoding. first_rotation_gate (ParameterGate): One of the rotation gate RX, RY or RZ. second_rotation_gate (ParameterGate): One of the rotation gate RX, RY or RZ. num_repeats (int): Number of encoding iterations. Examples: >>> import numpy as np >>> from mindquantum.algorithm.nisq import IQPEncoding >>> iqp = IQPEncoding(3) >>> iqp.circuit q0: ──H────RZ(alpha0)────●───────────────────────────●─────────────────────────────────── │ │ q1: ──H────RZ(alpha1)────X────RZ(alpha0 * alpha1)────X────●───────────────────────────●── │ │ q2: ──H────RZ(alpha2)─────────────────────────────────────X────RZ(alpha1 * alpha2)────X── >>> iqp.circuit.params_name ['alpha0', 'alpha1', 'alpha2', 'alpha0 * alpha1', 'alpha1 * alpha2'] >>> iqp.circuit.params_name >>> a = np.array([0, 1, 2]) >>> iqp.data_preparation(a) array([0, 1, 2, 0, 2]) >>> iqp.circuit.get_qs(pr=iqp.data_preparation(a)) array([-0.28324704-0.21159186j, -0.28324704-0.21159186j, 0.31027229+0.16950252j, 0.31027229+0.16950252j, 0.02500938+0.35266773j, 0.02500938+0.35266773j, 0.31027229+0.16950252j, 0.31027229+0.16950252j]) """ def __init__(self, n_feature, first_rotation_gate=RZ, second_rotation_gate=RZ, num_repeats=1): """Initialize an IQPEncoding object.""" _check_int_type("n_feature", n_feature) _check_value_should_not_less("n_feature", 1, n_feature) _check_int_type("num_repeats", num_repeats) _check_value_should_not_less("num_repeats", 1, num_repeats) _check_intrinsconeparagate("first_rotation_gate", first_rotation_gate) _check_intrinsconeparagate("second_rotation_gate", second_rotation_gate) self.n_feature = n_feature self.first_rotation_gate = first_rotation_gate self.second_rotation_gate = second_rotation_gate self.num_repeats = num_repeats super().__init__("IQPEncoding", n_feature) def _implement(self): # pylint: disable=arguments-differ """Implement of iqp encoding ansatz.""" self._circuit = UN(H, self.n_feature) repeat_unit = Circuit() for i in range(self.n_feature): repeat_unit += self.first_rotation_gate(f'alpha{i}').on(i) for i in range(1, self.n_feature): repeat_unit += X.on(i, i - 1) repeat_unit += self.second_rotation_gate(f'alpha{i - 1} * alpha{i}').on(i) repeat_unit += X.on(i, i - 1) repeat_unit += BARRIER self._circuit += repeat_unit * self.num_repeats
[文档] def data_preparation(self, data): r""" Prepare the classical data into suitable dimension for IQPEncoding. The IQPEncoding ansatz provides an ansatz to encode classical data into quantum state. Suppose the origin data has :math:`n` features, then the output data will have :math:`2n-1` features, with first :math:`n` features will be the original data. For :math:`m > n`, .. math:: \text{data}_m = \text{data}_{m - n} * \text{data}_{m - n - 1} Args: data ([list, numpy.ndarray]): The classical data need to encode with IQPEncoding ansatz. Returns: numpy.ndarray, the prepared data that is suitable for this ansatz. """ _check_input_type("data", (list, np.ndarray), data) if isinstance(data, list): data = np.array(data) output = data * 1 if len(output.shape) == 1: if output.shape[0] != self.n_feature: raise ValueError( f"This iqp encoding requires {self.n_feature} features, but data has {output.shape[0]} features" ) output = np.append(output, output[:-1] * output[1:]) return output if len(output.shape) == 2: if output.shape[1] != self.n_feature: raise ValueError( f"This iqp encoding requires {self.n_feature} features, but data has {output.shape[1]} features" ) return np.append(output, output[:, :-1] * output[:, 1:], axis=1) raise ValueError(f"data need a one or two dimension array, but get dimension of {data.shape}")