# Copyright 2018-2021 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.# pylint: disable=protected-access"""This module contains the qml.var measurement."""fromcollections.abcimportSequencefromtypingimportOptional,Unionimportpennylaneasqmlfrompennylane.operationimportOperatorfrompennylane.wiresimportWiresfrom.measurementsimportSampleMeasurement,StateMeasurement,Variancefrom.mid_measureimportMeasurementValuefrom.sampleimportSampleMP
[docs]defvar(op:Union[Operator,MeasurementValue])->"VarianceMP":r"""Variance of the supplied observable. Args: op (Union[Operator, MeasurementValue]): a quantum observable object. To get variances for mid-circuit measurements, ``op`` should be a ``MeasurementValue``. Returns: VarianceMP: Measurement process instance **Example:** .. code-block:: python3 dev = qml.device("default.qubit", wires=2) @qml.qnode(dev) def circuit(x): qml.RX(x, wires=0) qml.Hadamard(wires=1) qml.CNOT(wires=[0, 1]) return qml.var(qml.Y(0)) Executing this QNode: >>> circuit(0.5) 0.7701511529340698 """ifisinstance(op,MeasurementValue):returnVarianceMP(obs=op)ifisinstance(op,Sequence):raiseValueError("qml.var does not support measuring sequences of measurements or observables")returnVarianceMP(obs=op)
[docs]classVarianceMP(SampleMeasurement,StateMeasurement):"""Measurement process that computes the variance of the supplied observable. Please refer to :func:`pennylane.var` for detailed documentation. Args: obs (Union[.Operator, .MeasurementValue]): The observable that is to be measured as part of the measurement process. Not all measurement processes require observables (for example ``Probability``); this argument is optional. wires (.Wires): The wires the measurement process applies to. This can only be specified if an observable was not provided. eigvals (array): A flat array representing the eigenvalues of the measurement. This can only be specified if an observable was not provided. id (str): custom label given to a measurement instance, can be useful for some applications where the instance has to be identified """_shortname=Variance#! Note: deprecated. Change the value to "var" in v0.42@propertydefnumeric_type(self):returnfloat
[docs]defprocess_samples(self,samples:Sequence[complex],wire_order:Wires,shot_range:Optional[tuple[int,...]]=None,bin_size:Optional[int]=None,):# estimate the varianceop=self.mvifself.mvisnotNoneelseself.obswithqml.queuing.QueuingManager.stop_recording():samples=SampleMP(obs=op,eigvals=self._eigvals,wires=self.wiresifself._eigvalsisnotNoneelseNone,).process_samples(samples=samples,wire_order=wire_order,shot_range=shot_range,bin_size=bin_size)# With broadcasting, we want to take the variance over axis 1, which is the -1st/-2nd with/# without bin_size. Without broadcasting, axis 0 is the -1st/-2nd with/without bin_sizeaxis=-1ifbin_sizeisNoneelse-2# TODO: do we need to squeeze here? Maybe remove with new return typesreturnqml.math.squeeze(qml.math.var(samples,axis=axis))
[docs]defprocess_state(self,state:Sequence[complex],wire_order:Wires):# This also covers statistics for mid-circuit measurements manipulated using# arithmetic operators# we use ``wires`` instead of ``op`` because the observable was# already applied to the statewithqml.queuing.QueuingManager.stop_recording():prob=qml.probs(wires=self.wires).process_state(state=state,wire_order=wire_order)# In case of broadcasting, `prob` has two axes and these are a matrix-vector productsreturnself._calculate_variance(prob)
[docs]defprocess_density_matrix(self,density_matrix:Sequence[complex],wire_order:Wires):# This also covers statistics for mid-circuit measurements manipulated using# arithmetic operators# we use ``wires`` instead of ``op`` because the observable was# already applied to the statewithqml.queuing.QueuingManager.stop_recording():prob=qml.probs(wires=self.wires).process_density_matrix(density_matrix=density_matrix,wire_order=wire_order)# In case of broadcasting, `prob` has two axes and these are a matrix-vector productsreturnself._calculate_variance(prob)
def_calculate_variance(self,probabilities):""" Calculate the variance of a set of probabilities. Args: probabilities (array): the probabilities of collapsing to eigen states """eigvals=qml.math.asarray(self.eigvals(),dtype="float64")returnqml.math.dot(probabilities,(eigvals**2))-qml.math.dot(probabilities,eigvals)**2