Source code for pennylane.labs.resource_estimation.resource_operator
# Copyright 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.
r"""Abstract base class for resource operators."""
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Callable, Dict
if TYPE_CHECKING:
from pennylane.labs.resource_estimation import CompressedResourceOp
# pylint: disable=unused-argument
[docs]class ResourceOperator(ABC):
r"""Abstract class that defines the methods a PennyLane Operator
must implement in order to be used for resource estimation.
.. details::
**Example**
A PennyLane Operator can be extended for resource estimation by creating a new class that
inherits from both the ``Operator`` and ``ResourceOperator``. Here is an example showing how to
extend ``qml.QFT`` for resource estimation.
.. code-block:: python
import pennylane as qml
from pennylane.labs.resource_estimation import CompressedResourceOp, ResourceOperator
class ResourceQFT(qml.QFT, ResourceOperator):
@staticmethod
def _resource_decomp(num_wires) -> Dict[CompressedResourceOp, int]:
gate_types = {}
hadamard = ResourceHadamard.resource_rep()
swap = ResourceSWAP.resource_rep()
ctrl_phase_shift = ResourceControlledPhaseShift.resource_rep()
gate_types[hadamard] = num_wires
gate_types[swap] = num_wires // 2
gate_types[ctrl_phase_shift] = num_wires*(num_wires - 1) // 2
return gate_types
def resource_params(self, num_wires) -> dict:
return {"num_wires": num_wires}
@classmethod
def resource_rep(cls, num_wires) -> CompressedResourceOp:
params = {"num_wires": num_wires}
return CompressedResourceOp(cls, params)
Which can be instantiated as a normal operation, but now contains the resources:
.. code-block:: bash
>>> op = ResourceQFT(range(3))
>>> op.resources(**op.resource_params())
{Hadamard(): 3, SWAP(): 1, ControlledPhaseShift(): 3}
"""
@staticmethod
@abstractmethod
def _resource_decomp(*args, **kwargs) -> Dict[CompressedResourceOp, int]:
"""Returns a dictionary to be used for internal tracking of resources. This method is only to be used inside
the methods of classes inheriting from ResourceOperator."""
[docs] @classmethod
def resources(cls, *args, **kwargs) -> Dict[CompressedResourceOp, int]:
"""Returns a dictionary containing the counts of each operator type used to
compute the resources of the operator."""
return cls._resource_decomp(*args, **kwargs)
[docs] @classmethod
def set_resources(cls, new_func: Callable) -> None:
"""Set a custom resource method."""
cls.resources = new_func
[docs] @abstractmethod
def resource_params(self) -> dict:
"""Returns a dictionary containing the minimal information needed to
compute a compressed representation"""
[docs] @classmethod
@abstractmethod
def resource_rep(cls, *args, **kwargs) -> CompressedResourceOp:
"""Returns a compressed representation containing only the parameters of
the Operator that are needed to compute a resource estimation."""
[docs] def resource_rep_from_op(self) -> CompressedResourceOp:
"""Returns a compressed representation directly from the operator"""
return self.__class__.resource_rep(**self.resource_params())
[docs] @classmethod
def adjoint_resource_decomp(cls, *args, **kwargs) -> Dict[CompressedResourceOp, int]:
"""Returns a compressed representation of the adjoint of the operator"""
raise ResourcesNotDefined
[docs] @classmethod
def controlled_resource_decomp(
cls, num_ctrl_wires, num_ctrl_values, num_work_wires, *args, **kwargs
) -> Dict[CompressedResourceOp, int]:
"""Returns a compressed representation of the controlled version of the operator"""
raise ResourcesNotDefined
[docs] @classmethod
def pow_resource_decomp(cls, z, *args, **kwargs) -> Dict[CompressedResourceOp, int]:
"""Returns a compressed representation of the operator raised to a power"""
raise ResourcesNotDefined
[docs] @classmethod
def tracking_name(cls, *args, **kwargs) -> str:
"""Returns a name used to track the operator during resource estimation."""
return cls.__name__.replace("Resource", "")
[docs] def tracking_name_from_op(self) -> str:
"""Returns the tracking name built with the operator's parameters."""
return self.__class__.tracking_name(**self.resource_params())
[docs]class ResourcesNotDefined(Exception):
"""Exception to be raised when a ``ResourceOperator`` does not implement _resource_decomp"""
_modules/pennylane/labs/resource_estimation/resource_operator
Download Python script
Download Notebook
View on GitHub