Source code for pennylane.labs.resource_estimation.templates.stateprep
# Copyright 2025 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"""Resource operators for state preparation templates."""
import math
from pennylane.labs import resource_estimation as plre
from pennylane.labs.resource_estimation.qubit_manager import AllocWires
from pennylane.labs.resource_estimation.resource_operator import (
CompressedResourceOp,
GateCount,
ResourceOperator,
resource_rep,
)
# pylint: disable=arguments-differ, unused-argument
[docs]
class ResourceUniformStatePrep(ResourceOperator):
r"""Resource class for preparing a uniform superposition.
This operation prepares a uniform superposition over a given number of
basis states. The uniform superposition is defined as:
.. math::
\frac{1}{\sqrt{l}} \sum_{i=0}^{l} |i\rangle
where :math:`l` is the number of states.
This operation uses ``Hadamard`` gates to create the uniform superposition when
the number of states is a power of two. If the number of states is not a power of two,
amplitude amplification technique defined in
`arXiv:1805.03662 <https://arxiv.org/pdf/1805.03662>`_ is used.
Args:
num_states (int): the number of states in the uniform superposition
wires (Sequence[int], optional): the wires the operation acts on
Resources:
The resources are obtained from Figure 12 in `arXiv:1805.03662 <https://arxiv.org/pdf/1805.03662>`_.
The circuit uses amplitude amplification to prepare a uniform superposition over :math:`l`
basis states.
**Example**
The resources for this operation are computed using:
>>> unif_state_prep = plre.ResourceUniformStatePrep(10)
>>> print(plre.estimate_resources(unif_state_prep))
--- Resources: ---
Total qubits: 5
Total gates : 124
Qubit breakdown:
clean qubits: 1, dirty qubits: 0, algorithmic qubits: 4
Gate breakdown:
{'Hadamard': 16, 'X': 12, 'CNOT': 4, 'Toffoli': 4, 'T': 88}
"""
resource_keys = {"num_states"}
def __init__(self, num_states, wires=None):
self.num_states = num_states
k = (num_states & -num_states).bit_length() - 1
L = num_states // (2**k)
if L == 1:
self.num_wires = k
else:
self.num_wires = k + int(math.ceil(math.log2(L)))
super().__init__(wires=wires)
@property
def resource_params(self):
r"""Returns a dictionary containing the minimal information needed to compute the resources.
Returns:
dict: A dictionary containing the resource parameters:
* num_states (int): the number of states over which the uniform superposition is being prepared
"""
return {"num_states": self.num_states}
[docs]
@classmethod
def resource_rep(cls, num_states: int) -> CompressedResourceOp:
r"""Returns a compressed representation containing only the parameters of
the Operator that are needed to compute the resources.
Returns:
CompressedResourceOp: the operator in a compressed representation
"""
return CompressedResourceOp(cls, {"num_states": num_states})
[docs]
@classmethod
def default_resource_decomp(cls, num_states, **kwargs):
r"""Returns a list representing the resources of the operator. Each object in the list represents a gate and the
number of times it occurs in the circuit.
Args:
num_states (int): the number of states over which the uniform superposition is being prepared
Resources:
The resources are obtained from Figure 12 in `arXiv:1805.03662 <https://arxiv.org/pdf/1805.03662>`_.
The circuit uses amplitude amplification to prepare a uniform superposition over :math:`l` basis states.
Returns:
list[GateCount]: A list of GateCount objects, where each object
represents a specific quantum gate and the number of times it appears
in the decomposition.
"""
gate_lst = []
k = (num_states & -num_states).bit_length() - 1
L = num_states // (2**k)
if L == 1:
gate_lst.append(GateCount(resource_rep(plre.ResourceHadamard), k))
return gate_lst
logl = int(math.ceil(math.log2(L)))
gate_lst.append(GateCount(resource_rep(plre.ResourceHadamard), k + 3 * logl))
gate_lst.append(
GateCount(
resource_rep(plre.ResourceIntegerComparator, {"value": L, "register_size": logl}), 1
)
)
gate_lst.append(GateCount(resource_rep(plre.ResourceRZ), 2))
gate_lst.append(
GateCount(
resource_rep(
plre.ResourceAdjoint,
{
"base_cmpr_op": resource_rep(
plre.ResourceIntegerComparator, {"value": L, "register_size": logl}
)
},
),
1,
)
)
return gate_lst
[docs]
class ResourceAliasSampling(ResourceOperator):
r"""Resource class for preparing a state using coherent alias sampling.
Args:
num_coeffs (int): the number of unique coefficients in the state
precision (float): the precision with which the coefficients are loaded
wires (Sequence[int], optional): the wires the operation acts on
Resources:
The resources are obtained from Section III D in `arXiv:1805.03662 <https://arxiv.org/pdf/1805.03662>`_.
The circuit uses coherent alias sampling to prepare a state with the given coefficients.
**Example**
The resources for this operation are computed using:
>>> alias_sampling = plre.ResourceAliasSampling(num_coeffs=100)
>>> print(plre.estimate_resources(alias_sampling))
--- Resources: ---
Total qubits: 81
Total gates : 6.157E+3
Qubit breakdown:
clean qubits: 6, dirty qubits: 68, algorithmic qubits: 7
Gate breakdown:
{'Hadamard': 730, 'X': 479, 'CNOT': 4.530E+3, 'Toffoli': 330, 'T': 88}
"""
resource_keys = {"num_coeffs", "precision"}
def __init__(self, num_coeffs, precision=None, wires=None):
self.num_coeffs = num_coeffs
self.precision = precision
self.num_wires = int(math.ceil(math.log2(num_coeffs)))
super().__init__(wires=wires)
@property
def resource_params(self):
r"""Returns a dictionary containing the minimal information needed to compute the resources.
Returns:
dict: A dictionary containing the resource parameters:
* num_coeffs (int): the number of unique coefficients in the state
* precision (float): the precision with which the coefficients are loaded
"""
return {"num_coeffs": self.num_coeffs, "precision": self.precision}
[docs]
@classmethod
def resource_rep(cls, num_coeffs, precision=None) -> CompressedResourceOp:
r"""Returns a compressed representation containing only the parameters of
the Operator that are needed to compute the resources.
Returns:
CompressedResourceOp: the operator in a compressed representation
"""
return CompressedResourceOp(cls, {"num_coeffs": num_coeffs, "precision": precision})
[docs]
@classmethod
def default_resource_decomp(cls, num_coeffs, precision=None, **kwargs) -> list[GateCount]:
r"""Returns a list representing the resources of the operator. Each object in the list represents a gate and the
number of times it occurs in the circuit.
Args:
num_coeffs (int): the number of unique coefficients in the state
precision (float): the precision with which the coefficients are loaded
Resources:
The resources are obtained from Section III D in `arXiv:1805.03662 <https://arxiv.org/pdf/1805.03662>`_.
The circuit uses coherent alias sampling to prepare a state with the given coefficients.
Returns:
list[GateCount]: A list of GateCount objects, where each object
represents a specific quantum gate and the number of times it appears
in the decomposition.
"""
gate_lst = []
logl = int(math.ceil(math.log2(num_coeffs)))
precision = precision or kwargs["config"]["precision_alias_sampling"]
num_prec_wires = abs(math.floor(math.log2(precision)))
gate_lst.append(AllocWires(logl + 2 * num_prec_wires + 1))
gate_lst.append(
GateCount(resource_rep(plre.ResourceUniformStatePrep, {"num_states": num_coeffs}), 1)
)
gate_lst.append(GateCount(resource_rep(plre.ResourceHadamard), num_prec_wires))
gate_lst.append(
GateCount(
resource_rep(
plre.ResourceQROM,
{"num_bitstrings": num_coeffs, "size_bitstring": logl + num_prec_wires},
),
1,
)
)
gate_lst.append(
GateCount(
resource_rep(
plre.ResourceRegisterComparator,
{"first_register": num_prec_wires, "second_register": num_prec_wires},
),
1,
)
)
gate_lst.append(GateCount(resource_rep(plre.ResourceCSWAP), logl))
return gate_lst
_modules/pennylane/labs/resource_estimation/templates/stateprep
Download Python script
Download Notebook
View on GitHub