qrisp.operators.qubit.QubitOperator.expectation_value#
- QubitOperator.expectation_value(state_prep, precision=0.01, diagonalisation_method='commuting_qw', backend=None, compile=True, compilation_kwargs={}, subs_dic={}, precompiled_qc=None, measurement_data=None)[source]#
The
expectation valuefunction allows to estimate the expectation value of a Hamiltonian for a state that is specified by a preparation procedure. This preparation procedure can be supplied via a Python function that returns a QuantumVariable.Note that this method measures the hermitized version of the operator:
\[H = (O + O^\dagger)/2\]Note
When used with Jasp, only
state_prep,precisionanddiagonalisation_methodare relevant parameters. Additional parameters are ignored.- Parameters:
- state_prepcallable
A function returning a QuantumVariable. The expectation of the Hamiltonian for the state of this QuantumVariable will be measured. The state preparation function can only take classical values as arguments. This is because a quantum value would need to be copied for each sampling iteration, which is prohibited by the no-cloning theorem.
- precisionfloat, optional
The precision with which the expectation of the Hamiltonian is to be evaluated. The default is 0.01. The number of shots scales quadratically with the inverse precision.
- diagonalisation_methodstr, optional
Specifies the method for grouping and diagonalizing the QubitOperator. Available are
commuting_qw, i.e., the operator is grouped based on qubit-wise commutativity of terms, andcommuting, i.e., the operator is grouped based on commutativity of terms. The default iscommuting_qw.- backendBackendLike, optional
The backend on which to evaluate the quantum circuit. The default can be specified in the file default_backend.py.
- compilebool, optional
Boolean indicating if the .compile method of the underlying QuantumSession should be called before. The default is
True.- compilation_kwargsdict, optional
Keyword arguments for the compile method. For more details check
QuantumSession.compile. The default is{}.- subs_dicdict, optional
A dictionary of Sympy symbols and floats to specify parameters in the case of a circuit with unspecified, abstract parameters. The default is
{}.- precompiled_qcQuantumCircuit, optional
A precompiled quantum circuit.
- measurement_dataQubitOperatorMeasurement
Cached data to accelerate the measurement procedure. Automatically generated by default.
- Returns:
- callable
A function returning an array containing the expectaion value.
Examples
We define a Hamiltonian, and measure its expectation value for the state of a QuantumFloat.
We prepare the state
\[\ket{\psi_{\theta}} = (\cos(\theta)\ket{0}+\sin(\theta)\ket{1})^{\otimes 2}\]from qrisp import * from qrisp.operators import X,Y,Z import numpy as np def state_prep(theta): qv = QuantumFloat(2) ry(theta,qv) return qv
And compute the expectation value of the Hamiltonion \(H=Z_0Z_1\) for the state \(\ket{\psi_{\theta}}\)
H = Z(0)*Z(1) ev_function = H.expectation_value(state_prep) print(ev_function(np.pi/2)) # Yields: 0.010126265783222899
Similiarly, expectation values can be calculated with Jasp
@jaspify(terminal_sampling=True) def main(): H = Z(0)*Z(1) ev_function = H.expectation_value(state_prep) return ev_function(np.pi/2) print(main()) # Yields: 0.010126265783222899
Inspecting the circuits sent to the backend
When evaluating an expectation value, the operator is grouped by commutativity, change-of-basis gates are appended to the state preparation circuit, and one circuit per group is submitted to the backend — details that are not obvious from the operator expression. You can inspect these circuits by passing a
QrispSimulatorBackendwith aPassManagerthat ends withvisualize():from qrisp import QuantumFloat, ry, PassManager, visualize, decompose from qrisp.operators import X, Z from qrisp.interface import QrispSimulatorBackend import numpy as np def state_prep(theta): qv = QuantumFloat(2) ry(theta, qv) return qv H = X(0)*Z(1) + Z(0)*X(1) + X(0) pm = PassManager() pm += decompose() pm += visualize backend = QrispSimulatorBackend(pm=pm) ev_function = H.expectation_value(state_prep, backend=backend) result = ev_function(np.pi/2)
┌─────────┐┌───┐┌─┐ qv.0: ┤ Ry(π/2) ├┤ H ├┤M├ ├─────────┤└┬─┬┘└╥┘ qv.1: ┤ Ry(π/2) ├─┤M├──╫─ └─────────┘ └╥┘ ║ cb_15: ═════════════╬═══╩═ ║ cb_16: ═════════════╩═════ ┌─────────┐ ┌─┐ qv.0: ┤ Ry(π/2) ├─────┤M├─── ├─────────┤┌───┐└╥┘┌─┐ qv.1: ┤ Ry(π/2) ├┤ H ├─╫─┤M├ └─────────┘└───┘ ║ └╥┘ cb_21: ═════════════════╩══╬═ ║ cb_22: ════════════════════╩═The operator contains three terms.
X(0)*Z(1)andX(0)commute qubit-wise and are measured together in the first circuit (an H gate rotates X to Z on qubit 0).Z(0)*X(1)does not commute with the others and requires a separate circuit (with an H gate on qubit 1).visualize()reveals exactly which circuits reach the backend and how the basis rotations are applied.