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

# 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.
# ============================================================================
"""Strongly entangling ansatz."""

from mindquantum.core.circuit import Circuit, add_prefix, add_suffix
from mindquantum.core.gates import BasicGate
from mindquantum.core.gates.basicgate import U3
from mindquantum.utils.type_value_check import (
    _check_input_type,
    _check_int_type,
    _check_value_should_not_less,
)

from .._ansatz import Ansatz


[文档]class StronglyEntangling(Ansatz): # pylint: disable=too-few-public-methods r""" Strongly entangling ansatz. Please refers `Circuit-centric quantum classifiers <https://arxiv.org/pdf/1804.00633.pdf>`_. Args: n_qubits (int): number of qubit that this ansatz act on. depth (int): the depth of ansatz. entangle_gate (BasicGate): a quantum gate to generate entanglement. If a single qubit gate is given, a control qubit will add, if a two qubits gate is given, the two qubits gate will act on different qubits. prefix (str): The prefix of parameters. Default: ``''``. suffix (str): The suffix of parameters. Default: ``''``. Examples: >>> from mindquantum.core.gates import X >>> from mindquantum.algorithm.nisq import StronglyEntangling >>> ansatz = StronglyEntangling(3, 2, X) >>> ansatz.circuit ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┏━━━┓ q0: ──┨ U3(θ=l0_a0, φ=l0_b0, λ=l0_c0) ┠───■─────────┨╺╋╸┠─↯─ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┗━┳━┛ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┏━┻━┓ ┃ q1: ──┨ U3(θ=l0_a1, φ=l0_b1, λ=l0_c1) ┠─┨╺╋╸┠───■─────╂───↯─ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┗━━━┛ ┃ ┃ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┏━┻━┓ ┃ q2: ──┨ U3(θ=l0_a2, φ=l0_b2, λ=l0_c2) ┠───────┨╺╋╸┠───■───↯─ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┗━━━┛ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┏━━━┓ q0: ──┨ U3(θ=l1_a0, φ=l1_b0, λ=l1_c0) ┠───■───┨╺╋╸┠───────── ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┗━┳━┛ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ ┃ ┏━━━┓ q1: ──┨ U3(θ=l1_a1, φ=l1_b1, λ=l1_c1) ┠───╂─────■───┨╺╋╸┠─── ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┃ ┗━┳━┛ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┏━┻━┓ ┃ q2: ──┨ U3(θ=l1_a2, φ=l1_b2, λ=l1_c2) ┠─┨╺╋╸┠─────────■───── ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ┗━━━┛ """ # pylint: disable=too-many-arguments def __init__(self, n_qubits: int, depth: int, entangle_gate: BasicGate, prefix: str = '', suffix: str = ''): """Initialize a strongly entangling ansatz.""" _check_int_type('n_qubits', n_qubits) _check_int_type('depth', depth) _check_value_should_not_less('n_qubits', 2, n_qubits) _check_value_should_not_less('depth', 1, depth) _check_input_type('prefix', str, prefix) _check_input_type('suffix', str, suffix) if not isinstance(entangle_gate, BasicGate) or entangle_gate.parameterized: raise ValueError(f"entangle gate requires a non parameterized gate, but get {entangle_gate}") m_dim = entangle_gate.matrix().shape[0] if m_dim == 2: self.gate_qubits = 1 elif m_dim == 4: self.gate_qubits = 2 else: raise ValueError( f"error gate, entangle_gate can only be one qubit or two qubits, but get dimension with {m_dim}" ) self.prefix = prefix self.suffix = suffix super().__init__('Strongly Entangling', n_qubits, depth, entangle_gate) def _implement(self, depth, entangle_gate): # pylint: disable=arguments-differ """Implement of strongly entangling ansatz.""" rot_part_ansatz = Circuit([U3(f'a{i}', f'b{i}', f'c{i}').on(i) for i in range(self.n_qubits)]) circ = Circuit() loop = 1 for current_depth in range(depth): circ += add_prefix(rot_part_ansatz, f'l{current_depth}') if (current_depth + loop) % self.n_qubits == 0: loop += 1 for idx in range(self.n_qubits): if self.gate_qubits == 1: circ += entangle_gate.on((idx + current_depth + loop) % self.n_qubits, idx) else: circ += entangle_gate.on([(idx + current_depth + loop) % self.n_qubits, idx]) self._circuit = circ if self.prefix: self._circuit = add_prefix(self._circuit, self.prefix) if self.suffix: self._circuit = add_suffix(self._circuit, self.suffix)