Estimators
このチュートリアルでは、与えられた状態に関する演算子の期待値を計算する方法を紹介します。
QURI Partsでは、演算子の期待値推定はEstimatorによって行われます。QURI Partsには様々なタイプのEstimatorがあります。このチュートリアルでは、純粋  状態の演算子の正確な期待値を計算することに焦点をあてます。QURI Partsで現在使用可能なEstimatorsをこのページの下にまとめました。
インターフェース
ここでQURI Partsの2種類のEstimatorのインターフェースを紹介します:QuantumEstimatorとConcurrentQuantumEstimatorです。
これらは計算を行うための具体的な実装が必要な抽象的な関数です。ここでは、初めに定義と関連のある用語について紹介します:
- 
Estimatable:OperatorかPauliLabelを表しています。
- 
Estimate:Estimateは値プロパティとエラープロパティを含むオブジェクトです。
- 
QuantumEstimator:QuantumEstimatorは第一引数としてEstimatableをとり、第二引数としてCircuitQuantumStateかQuantumStateVectorをとる関数で、Estimateが返却されます。Estimateは推定期待値と推定値のエラーを表しています。
- 
ConcurrentQuantumEstimator:ConcurrentQuantumEstimatorはEstimatableと量子状態の複数ペアの期待値を推定する関数です。
以下にその関数のシグネチャを示します:
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]],
]
Estimatorの作成と実行
このセクションでは、quri_parts.qulacsパッケージによって提供されるQuantumEstimatorとConcurrentQuantumEstimatorの具体的なインスタンスについて紹介します。これらをどのように作成し、計算するかを示します。ここで紹介するEstimatorは、正確なEstimatorなので、返されるEstimateの誤差はerrorプロパティは0になります。
QURI Partsで  は、複数のEstimatorの作成関数があり、それらはcreate_..._estimatorと名付けられています。Estimatorのオブジェクトは作成関数の実行によって得ることができます。ここで紹介します:
- create_qulacs_vector_estimator
- create_qulacs_vector_concurrent_estimator
いくつかの演算子と推定するための状態を用意しましょう。
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
ここではquri_parts.qulacsパッケージのVector Estimatorについて紹介します。Vector Estimatorは正確な純粋状態の期待値を計算するEstimatorで、例えば、以下のような計算を行います。
 はCircuitQuantumStateかQuantumStateVectorのいずれかです。まずは、Vector Estimatorを作成します:
from quri_parts.qulacs.estimator import create_qulacs_vector_estimator
qulacs_estimator = create_qulacs_vector_estimator()
このVector Estimatorにより、ある状態に対するある演算子の期待値を推定することができます:
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
複数の演算子と複数の状態を一度に推定するConcurrentQuantumEstimatorインターフェースも存在します。インターフェースは以下のいずれかを受け付けます:
- 
1つの演算子、複数の状態 
- 
複数の演算子、1つの状態 
- 
同じ個数の演算子と状態 
はじめに、Concurrent Estimatorを作成します。
from quri_parts.qulacs.estimator import create_qulacs_vector_concurrent_estimator
qulacs_concurrent_estimator = create_qulacs_vector_concurrent_estimator()
上の通り、Concurrent Estimatorでは可能な入力が3種類あります。
- 演算子と状態が同じ個数の時の同時推定:
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)]
- 1つの演算子と複数の状態を同時推定:
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)]
- 複数の演算子と1つの状態の同時推定:
qulacs_concurrent_estimator([op1, op2, op3], [state1])
#output
    [_Estimate(value=(7.9999999999999964+0j), error=0.0),
     _Estimate(value=0j, error=0.0),
     _Estimate(value=0j, error=0.0)]
Qulacsの場合、concurrent.futures.Executor(デフォルトでは並行処理をしないNone)とconcurrency(デフォルトでは1)を指定してConcurrentQuantumEstimatorを作成することができます。Qulacsそのものではマルチスレッドをサポートしておらず、ThreadPoolExecutorとProcessPoolExecutorを使用してもパフォーマンスの改善にはならない可能性があることに注意してください。
from concurrent.futures import ThreadPoolExecutor
from quri_parts.qulacs.estimator import create_qulacs_vector_concurrent_estimator
executor = ThreadPoolExecutor(max_workers=4)
qulacs_concurrent_estimator = create_qulacs_vector_concurrent_estimator(executor, concurrency=4)
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)]
QURI Partsで現在使用可能なEstimators
このセクションでは、QURI Partsで全ての使用可能なEstimatorについてまとめました。以下にそれらの一覧と、何をするのかについての簡単な説明を示します。Estimatorsは以下のグループで分類されます:
- Quantum estimators
- Parametric estimators
- Overlapping esimtators
- Sampling estimators
- Error mitigation estimators
Quantum estimators
最初に、ノイズのない、もしくはノイズのある系での正確な期待値の計算を行う使用可能なQuantum estimatorsをまとめます。density matrix estimatorsのために、ノイズありシミュレーションチュートリアル内でどのようにこれらを使用するかについて紹介します。
| モジュール | 作成関数 | ノイズあり推定をサポートしているか | タイプ | 他のEstimatorに依存しているか | 
|---|---|---|---|---|
| quri_parts.qulacs | create_qulacs_vector_estimator(concurrent) | ✘ | (Concurrent)QuantumEstimator (State vector) | ✘ | 
| quri_parts.qulacs | create_qulacs_density_matrix_estimator(concurrent) | ✔ | (Concurrent)QuantumEstimator (density matrix) | ✘ | 
| quri_parts.itensor | create_itensor_mps_estimator(concurrent) | ✘ | (Concurrent)QuantumEstimator (MPS) | ✘ | 
| quri_parts.stim | create_stim_clifford_estimator(concurrent) | ✘ | (Concurrent)QuantumEstimator (Clifford) | ✘ | 
Parametric estimators
Parametric estimatorsはパラメトリック状態の期待値の推定を行うestimatorsです。これらは、パラメトリック状態のチュートリアルで紹介されています。つまり、以下を計算します。
は回路パラメータです。
QURI PartsにはさらにGradient estimatorsとHessian estimatorsの2種類の特別なparametric estimatorsがあります。これらは、回路パラメータのセットに関する期待値の勾配とヘッセ行列を計算します。
- 
GradientEstimator:
- 
HessianEstimator:
| モジュール | 作成関数 | ノイズあり推定をサポートしているか | タイプ | 他のestimatorsに依存しているか | 
|---|---|---|---|---|
| quri_parts.qulacs | create_qulacs_vector_parametric_estimator(concurrent) | ✘ | (Concurrent)ParametricQuantumEstimator(State vector) | ✘ | 
| quri_parts.qulacs | create_qulacs_density_matrix_parametric_estimator (concurrent) | ✔ | (Concurrent)ParametricQuantumEstimator(density matrix) | ✘ | 
| quri_parts.itensor | create_itensor_mps_parametric_estimator (concurrent) | ✘ | (Concurrent)ParametricQuantumEstimator (MPS) | ✘ | 
| quri_parts.core | create_numerical_gradient_estimator | ✔ (depends on input estimator) | GradientEstimator | ConcurrentParametricEstimator | 
| quri_parts.core | create_parameter_shift_gradient_estimator | ✔ (depends on input estimator) | GradientEstimator | ConcurrentParametricEstimator | 
| quri_parts.core | create_parameter_shift_hessian_estimator | ✔ (depends on input estimator) | HessianEstimator | ConcurrentParametricEstimator | 
"他のEstimatorに依存"という列は、他のEstimatorを使ってEstimatorを作成することを指します。そういったEstimatorを作成する際には、どのEstimatorを使用するかを明示的に指定します。
Overlapping estimators
他の期待値を推定するEstimatorに加えて、QURI Partsは2つの状態の内積の2乗を評価するEstimatorも提供します。
- OverlapEstimator: