Estimators
In this tutorial, we introduce how to compute expectation values of operators for a given state :
In QURI Parts, this is done by an Estimator
. There are various types of Estimator
s in QURI Parts. In this tutorial we focus on those that computes the exact expectation value of an operator on a pure state. We will also summarize all the currently available estimators in QURI Parts at the bottom of this page.
Interface
Here we introduce the interface of 2 estimators in QURI Parts: QuantumEstimator
and ConcurrentQuantumEstimator
. They are both abstract functions that need concrete implementations for us to perform any computation. Here, we first introduce their definitions and related terminologies:
-
Estimatable
: Represents anOperator
or aPauliLabel
. -
Estimate
: AnEstimate
is any object that contains avalue
property and anerror
property. -
QuantumEstimator
: AQuantumEstimator
is any function that takes anEstimatable
as its first argument, aCircuitQuantumState
orQuantumStateVector
as the second argument and returns anEstimate
. TheEstimate
represents the estimated expectation value and the error of the estimation. -
ConcurrentQuantumEstimator
: AConcurrentQuantumEstimator
is a function that estimates the expectation values of multiple pairs ofEstimatable
and quantum state.
We demonstrate their function signatures below:
from typing import Union, Callable, Iterable, Sequence
from typing_extensions import TypeAlias, TypeVar
from quri_parts.core.estimator import Estimate
from quri_parts.core.operator import Operator, PauliLabel
from quri_parts.core.state import CircuitQuantumState, QuantumStateVector
#: Represents either CircuitQuantumState or QuantumStateVector.
_StateT = TypeVar("_StateT", bound=Union[CircuitQuantumState, QuantumStateVector])
#: Represents either Operator or PauliLabel.
Estimatable: TypeAlias = Union[Operator, PauliLabel]
#: A function that computes the expectation value of an operator on a given state.
QuantumEstimator: TypeAlias = Callable[[Estimatable, _StateT], Estimate[complex]]
#: A function that computes the expectation values of pairs of operators and states.
ConcurrentQuantumEstimator: TypeAlias = Callable[
[Sequence[Estimatable], Sequence[_StateT]],
Iterable[Estimate[complex]],
]
Create and execute estimators
In this section, we introduce concrete instances of QuantumEstimator
s and ConcurrentQuantumEstimator
s provided by the quri_parts.qulacs
package. We will demonstrate how to create them and perform computations with them. The estimators we introduce here are exact estimators, thus the error
property in the returned Estimate
will always be 0.
In QURI Parts, we provide several estimator creation functions, they are often named create_..._estimator
. You would obtain an estimator object by running the creation function. Here, we introduce:
create_qulacs_vector_estimator
create_qulacs_vector_concurrent_estimator
Let's first prepare some operators and states for us to estimate later
import numpy as np
from quri_parts.core.operator import pauli_label, Operator, PAULI_IDENTITY
op1 = Operator({
pauli_label("X0 Y1"): 2,
pauli_label("Z0 Y1"): 2j,
PAULI_IDENTITY: 8,
})
op2 = pauli_label("X0 Y1 Z3")
op3 = pauli_label("X0 X1 X3")
from quri_parts.core.state import quantum_state
from quri_parts.circuit import QuantumCircuit, X, CNOT, H
n_qubits = 4
state1 = quantum_state(
n_qubits, circuit=QuantumCircuit(n_qubits, gates=[X(0), H(1), H(2), CNOT(1, 2)])
)
state2 = quantum_state(n_qubits, bits=0b1101)
state3 = quantum_state(
n_qubits, vector=np.array(
[1/np.sqrt(2**n_qubits) for _ in range(2**n_qubits)]
)
)
Qulacs vector estimator
Here we introduce the vector estimator provided by the quri_parts.qulacs
package. A vector estimator is an estimator that computes the expectation value of an operator for a pure state exactly, i.e. it computes
with being either a CircuitQuantumState
or a QuantumStateVector
. Now, let's create a vector estimator:
from quri_parts.qulacs.estimator import create_qulacs_vector_estimator
qulacs_estimator = create_qulacs_vector_estimator()
With this vector estimator at hand, we can estimate the expectation values of a an operator for a given state:
print(qulacs_estimator(op1, state1))
print(qulacs_estimator(op2, state2))
print(qulacs_estimator(op3, state3))
#output
_Estimate(value=(7.9999999999999964+0j), error=0.0)
_Estimate(value=0j, error=0.0)
_Estimate(value=(1+0j), error=0.0)
Qulacs vector concurrent estimator
There is also a ConcurrentQuantumEstimator
interface, which estimates multiple operators and multiple states at once. The interface accept either one of the followings:
-
One operator, multiple states
-
Multiple operators, one state
-
The same number of operators and states
First, we create a concurrent estimator
from quri_parts.qulacs.estimator import create_qulacs_vector_concurrent_estimator
qulacs_concurrent_estimator = create_qulacs_vector_concurrent_estimator()
As mentioned above, there are 3 possible inputs to a concurrent estimator
- Estimate concurrently for the same number of operators and states:
qulacs_concurrent_estimator([op1, op2, op3], [state1, state2, state3])
#output
[_Estimate(value=(7.9999999999999964+0j), error=0.0),
_Estimate(value=0j, error=0.0),
_Estimate(value=(1+0j), error=0.0)]
- Estimate concurrently for one operator, multiple states.
qulacs_concurrent_estimator([op1], [state1, state2, state3])
#output
[_Estimate(value=(7.9999999999999964+0j), error=0.0),
_Estimate(value=(8+0j), error=0.0),
_Estimate(value=(8+0j), error=0.0)]
- Estimate concurrently for multiple operators, one state.
qulacs_concurrent_estimator([op1, op2, op3], [state1])