Source code for pennylane.templates.subroutines.qubitization
# Copyright 2018-2024 Xanadu Quantum Technologies Inc.# 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."""This submodule contains the template for Qubitization."""importcopyimportpennylaneasqmlfrompennylane.operationimportOperationfrompennylane.wiresimportWires
[docs]classQubitization(Operation):r"""Applies the `Qubitization <https://arxiv.org/abs/2204.11890>`__ operator. This operator encodes a Hamiltonian, written as a linear combination of unitaries, into a unitary operator. It is implemented with a quantum walk operator that takes a Hamiltonian as input and generates: .. math:: Q = \text{Prep}_{\mathcal{H}}^{\dagger} \text{Sel}_{\mathcal{H}} \text{Prep}_{\mathcal{H}}(2|0\rangle\langle 0| - I). .. seealso:: :class:`~.AmplitudeEmbedding` and :class:`~.Select`. Args: hamiltonian (Union[.Hamiltonian, .Sum, .Prod, .SProd, .LinearCombination]): The Hamiltonian written as a linear combination of unitaries. control (Iterable[Any], Wires): The control qubits for the Qubitization operator. **Example** This operator, when applied in conjunction with QPE, allows computing the eigenvalue of an eigenvector of the Hamiltonian. .. code-block:: H = qml.dot([0.1, 0.3, -0.3], [qml.Z(0), qml.Z(1), qml.Z(0) @ qml.Z(2)]) @qml.qnode(qml.device("default.qubit")) def circuit(): # initiate the eigenvector qml.PauliX(2) # apply QPE measurements = qml.iterative_qpe( qml.Qubitization(H, control = [3,4]), aux_wire = 5, iters = 3 ) return qml.probs(op = measurements) output = circuit() # post-processing lamb = sum([abs(c) for c in H.terms()[0]]) .. code-block:: pycon >>> print("eigenvalue: ", lamb * np.cos(2 * np.pi * (np.argmax(output)) / 8)) eigenvalue: 0.7 """grad_method=None@classmethoddef_primitive_bind_call(cls,*args,**kwargs):returncls._primitive.bind(*args,**kwargs)def__init__(self,hamiltonian,control,id=None):wires=qml.wires.Wires(control)+hamiltonian.wiresself._hyperparameters={"hamiltonian":hamiltonian,"control":qml.wires.Wires(control),}super().__init__(*hamiltonian.data,wires=wires,id=id)def_flatten(self):data=(self.hyperparameters["hamiltonian"],)metadata=tuple(itemforiteminself.hyperparameters.items()ifitem[0]!="hamiltonian")returndata,metadata@classmethoddef_unflatten(cls,data,metadata):returncls(*data,**dict(metadata))def__copy__(self):clone=Qubitization.__new__(Qubitization)# Ensure the operators in the hyper-parameters are copied instead of aliased.clone._hyperparameters={"hamiltonian":copy.copy(self._hyperparameters["hamiltonian"]),"control":copy.copy(self._hyperparameters["control"]),}forattr,valueinvars(self).items():ifattr!="_hyperparameters":setattr(clone,attr,value)returnclone
[docs]@staticmethoddefcompute_decomposition(*_,**kwargs):# pylint: disable=arguments-differr"""Representation of the operator as a product of other operators (static method). .. math:: O = O_1 O_2 \dots O_n. .. seealso:: :meth:`~.Qubitization.decomposition`. Args: *params (list): trainable parameters of the operator, as stored in the ``parameters`` attribute wires (Iterable[Any], Wires): wires that the operator acts on **hyperparams (dict): non-trainable hyperparameters of the operator, as stored in the ``hyperparameters`` attribute Returns: list[Operator]: decomposition of the operator **Example:** .. code-block:: python import pennylane as qml from pennylane.wires import Wires >>> print(qml.Qubitization.compute_decomposition(hamiltonian=0.1 * qml.Z(0), control=Wires(1))) [Reflection(3.141592653589793, wires=[1]), PrepSelPrep(coeffs=(0.1,), ops=(Z(0),), control=Wires([1]))] """hamiltonian=kwargs["hamiltonian"]control=kwargs["control"]decomp_ops=[]identity=qml.prod(*[qml.Identity(wire)forwireincontrol])decomp_ops.append(qml.Reflection(identity))decomp_ops.append(qml.PrepSelPrep(hamiltonian,control=control))returndecomp_ops