Japanese
言語
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

注釈

このページは tutorials/operators/02_gradients_framework.ipynb から生成されました。

Qiskit Gradient フレームワーク

gradient フレームワークにより、次の形の期待値の標準的な一次勾配に加えて、量子勾配やその関数の評価が可能になります。

\[\langle\psi\left(\theta\right)|\hat{O}\left(\omega\right)|\psi\left(\theta\right)\rangle\]

gradient フレームワークは、二次の勾配 (ヘシアン) の評価や、量子状態 \(|\psi\left(\theta\right)\rangle\) の量子フィッシャー情報量 (Quantum Fisher Information, QFI) の評価もサポートしています。

gradient_framework.png

インポート

[1]:
#General imports
import numpy as np

#Operator Imports
from qiskit.opflow import Z, X, I, StateFn, CircuitStateFn, SummedOp
from qiskit.opflow.gradients import Gradient, NaturalGradient, QFI, Hessian

#Circuit imports
from qiskit.circuit import QuantumCircuit, QuantumRegister, Parameter, ParameterVector, ParameterExpression
from qiskit.circuit.library import EfficientSU2

一次の勾配

入力状態 \(|\psi\rangle\)、パラメータ化されたAnsatz \(V\left(\theta\right)\) 、観測量 \(\hat{O}\left(\omega\right)=\sum_{i}\omega_i\hat{O}_i\) が与えられた時、以下を求めたいです。

測定演算子パラメーターに関する勾配

観測量 \(\hat{O}\left(\omega\right)\) の測定演算子の係数に関する期待値の勾配は、以下のようになります。

\[\frac{\partial\langle\psi\left(\theta\right)|\hat{O}\left(\omega\right)|\psi\left(\theta\right)\rangle}{\partial\omega_i} = \langle\psi\left(\theta\right)|\hat{O}_i\left(\omega\right)|\psi\left(\theta\right)\rangle.\]

まず、量子状態 \(|\psi\left(\theta\right)\rangle\) と観測量としてのハミルトニアン \(H\) を定義します。そして状態とハミルトニアンを、以下のように期待値を定義するオブジェクトとしてラップします。

\[\langle\psi\left(\theta\right)|H|\psi\left(\theta\right)\rangle.\]
[2]:
# Instantiate the quantum state
a = Parameter('a')
b = Parameter('b')
q = QuantumRegister(1)
qc = QuantumCircuit(q)
qc.h(q)
qc.rz(a, q[0])
qc.rx(b, q[0])

# Instantiate the Hamiltonian observable
H = (2 * X) + Z

# Combine the Hamiltonian observable and the state
op = ~StateFn(H) @ CircuitStateFn(primitive=qc, coeff=1.)

# Print the operator corresponding to the expectation value
print(op)
ComposedOp([
  OperatorMeasurement(2.0 * X
  + 1.0 * Z),
  CircuitStateFn(
        ┌───┐┌───────┐┌───────┐
  q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b) ├
        └───┘└───────┘└───────┘
  )
])

勾配を評価したいパラメータのリストを作ります。このリストと期待値の演算子は勾配を表す演算子を生成するために使われます。

[3]:
params = [a, b]

# Define the values to be assigned to the parameters
value_dict = {a: np.pi / 4, b: np.pi}

# Convert the operator and the gradient target params into the respective operator
grad = Gradient().convert(operator = op, params = params)

# Print the operator corresponding to the Gradient
print(grad)
ListOp([
  SummedOp([
    ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌─────────────────────────┐┌───────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a + 1.5707963267949) ├┤ RX(b) ├┤ H ├
            └───┘└─────────────────────────┘└───────┘└───┘
      )
    ]),
    -1.0 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌─────────────────────────┐┌───────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a - 1.5707963267949) ├┤ RX(b) ├┤ H ├
            └───┘└─────────────────────────┘└───────┘└───┘
      )
    ]),
    0.5 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌─────────────────────────┐┌───────┐
      q0_0: ┤ H ├┤ RZ(a + 1.5707963267949) ├┤ RX(b) ├
            └───┘└─────────────────────────┘└───────┘
      )
    ]),
    -0.5 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌─────────────────────────┐┌───────┐
      q0_0: ┤ H ├┤ RZ(a - 1.5707963267949) ├┤ RX(b) ├
            └───┘└─────────────────────────┘└───────┘
      )
    ])
  ]),
  SummedOp([
    ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌─────────────────────────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b + 1.5707963267949) ├┤ H ├
            └───┘└───────┘└─────────────────────────┘└───┘
      )
    ]),
    -1.0 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌─────────────────────────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b - 1.5707963267949) ├┤ H ├
            └───┘└───────┘└─────────────────────────┘└───┘
      )
    ]),
    0.5 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌─────────────────────────┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b + 1.5707963267949) ├
            └───┘└───────┘└─────────────────────────┘
      )
    ]),
    -0.5 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌─────────────────────────┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b - 1.5707963267949) ├
            └───┘└───────┘└─────────────────────────┘
      )
    ])
  ])
])

あとはパラメーターに値を代入して、勾配演算子を評価するだけです。

[4]:
# Assign the parameters and evaluate the gradient
grad_result = grad.assign_parameters(value_dict).eval()
print('Gradient', grad_result)
Gradient [(-1.414213562373094+0j), (-0.7071067811865474+0j)]

状態パラメーターに関する勾配

状態 \(|\psi\left(\theta\right)\rangle\) のパラメーターに関する期待値の勾配は以下のようになります。

\[\frac{\partial\langle\psi\left(\theta\right)|\hat{O}\left(\omega\right)|\psi\left(\theta\right)\rangle}{\partial\theta}\]

状態 \(|\psi\left(\theta\right)\rangle\) のパラメーターに関するサンプリング確率は、以下のようになります。

\[\frac{\partial p_i}{\partial\theta} = \frac{\partial\langle\psi\left(\theta\right)|i\rangle\langle i |\psi\left(\theta\right)\rangle}{\partial\theta}.\]

状態パラメーターに関する勾配は、別の方法でも評価することができます。それぞれの方法には、長所と短所があります。

[5]:
# Define the Hamiltonian with fixed coefficients
H = 0.5 * X - 1 * Z
# Define the parameters w.r.t. we want to compute the gradients
params = [a, b]
# Define the values to be assigned to the parameters
value_dict = { a: np.pi / 4, b: np.pi}

# Combine the Hamiltonian observable and the state into an expectation value operator
op = ~StateFn(H) @ CircuitStateFn(primitive=qc, coeff=1.)
print(op)
ComposedOp([
  OperatorMeasurement(0.5 * X
  - 1.0 * Z),
  CircuitStateFn(
        ┌───┐┌───────┐┌───────┐
  q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b) ├
        └───┘└───────┘└───────┘
  )
])

パラメーター・シフト勾配

二つの相異なる固有値 \(\pm r\) をもつエルミート演算子 \(g\) が、パラメータ化された量子ゲートの生成子として、与えられたとします

\[G(\theta)= e^{-i\theta g}.\]

そうすると、量子勾配は固有値 \(r\) に依存するパラメーターへのシフトによって計算することができます。全ての Qiskit の標準的なパラメータ化ゲート は、以下のように \(\pi/2\) でシフトすることができます。

\[\frac{\partial\langle\psi\left(\theta\right)|\hat{O}\left(\omega\right)|\psi\left(\theta\right)\rangle}{\partial\theta} = \left(\langle\psi\left(\theta+\pi/2\right)|\hat{O}\left(\omega\right)|\psi\left(\theta+\pi/2\right)\rangle -\langle\psi\left(\theta-\pi/2\right)|\hat{O}\left(\omega\right)|\psi\left(\theta-\pi/2\right)\rangle\right) / 2.\]

確率勾配も同様に計算されます。

[6]:
# Convert the expectation value into an operator corresponding to the gradient w.r.t. the state parameters using
# the parameter shift method.
state_grad = Gradient(grad_method='param_shift').convert(operator=op, params=params)
# Print the operator corresponding to the gradient
print(state_grad)
# Assign the parameters and evaluate the gradient
state_grad_result = state_grad.assign_parameters(value_dict).eval()
print('State gradient computed with parameter shift', state_grad_result)
ListOp([
  SummedOp([
    0.25 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌─────────────────────────┐┌───────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a + 1.5707963267949) ├┤ RX(b) ├┤ H ├
            └───┘└─────────────────────────┘└───────┘└───┘
      )
    ]),
    -0.25 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌─────────────────────────┐┌───────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a - 1.5707963267949) ├┤ RX(b) ├┤ H ├
            └───┘└─────────────────────────┘└───────┘└───┘
      )
    ]),
    -0.5 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌─────────────────────────┐┌───────┐
      q0_0: ┤ H ├┤ RZ(a + 1.5707963267949) ├┤ RX(b) ├
            └───┘└─────────────────────────┘└───────┘
      )
    ]),
    0.5 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌─────────────────────────┐┌───────┐
      q0_0: ┤ H ├┤ RZ(a - 1.5707963267949) ├┤ RX(b) ├
            └───┘└─────────────────────────┘└───────┘
      )
    ])
  ]),
  SummedOp([
    0.25 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌─────────────────────────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b + 1.5707963267949) ├┤ H ├
            └───┘└───────┘└─────────────────────────┘└───┘
      )
    ]),
    -0.25 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌─────────────────────────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b - 1.5707963267949) ├┤ H ├
            └───┘└───────┘└─────────────────────────┘└───┘
      )
    ]),
    -0.5 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌─────────────────────────┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b + 1.5707963267949) ├
            └───┘└───────┘└─────────────────────────┘
      )
    ]),
    0.5 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌─────────────────────────┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b - 1.5707963267949) ├
            └───┘└───────┘└─────────────────────────┘
      )
    ])
  ])
])
State gradient computed with parameter shift [(-0.35355339059327356+0j), (0.7071067811865472+0j)]

ユニタリー演算子の勾配の線形結合

ユニタリー行列は \(U\left(\omega\right) = e^{iM\left(\omega\right)}\) と書くことができます。ここで \(M\left(\omega\right)\) はパラメータ化されたエルミート行列です。さらにエルミート行列は次のように、 Pauli 行列の重み付き和に分解できます。\(M\left(\omega\right) = \sum_pm_p\left(\omega\right)h_p\) ここで、\(m_p\left(\omega\right)\in\mathbb{R}\)\(j\) 番目の量子ビットに作用する \(\sigma_{j, p}\in\left\{I, X, Y, Z\right\}\) に対して、\(h_p=\bigotimes\limits_{j=0}^{n-1}\sigma_{j, p}\) となっています。そのため、 \(U_k\left(\omega_k\right)\) の勾配は以下のように与えられます。 \begin{equation*} \frac{\partial U_k\left(\omega_k\right)}{\partial\omega_k} = \sum\limits_pi \frac{\partial m_{k,p}\left(\omega_k\right)}{\partial\omega_k}U_k\left(\omega_k\right)h_{k_p}. \end{equation*}

Simulating physical phenomena by quantum networks で提案されている回路構成と観測を組み合わせることで、単一の量子回路の評価で勾配を計算することができます。

[7]:
# Convert the expectation value into an operator corresponding to the gradient w.r.t. the state parameter using
# the linear combination of unitaries method.
state_grad = Gradient(grad_method='lin_comb').convert(operator=op, params=params)

# Print the operator corresponding to the gradient
print(state_grad)

# Assign the parameters and evaluate the gradient
state_grad_result = state_grad.assign_parameters(value_dict).eval()
print('State gradient computed with the linear combination method', state_grad_result)
ListOp([
  SummedOp([
    0.5 * ComposedOp([
      OperatorMeasurement(ZZ) * 2.0,
      CircuitStateFn(
             ┌───┐          ┌───────┐┌───────┐┌───┐
       q0_0: ┤ H ├────────■─┤ RZ(a) ├┤ RX(b) ├┤ H ├
             ├───┤┌─────┐ │ └─┬───┬─┘└───────┘└───┘
      q81_0: ┤ H ├┤ SDG ├─■───┤ H ├────────────────
             └───┘└─────┘     └───┘
      ) * 0.7071067811865476
    ]),
    -1.0 * ComposedOp([
      OperatorMeasurement(ZZ) * 2.0,
      CircuitStateFn(
             ┌───┐          ┌───────┐┌───────┐
       q0_0: ┤ H ├────────■─┤ RZ(a) ├┤ RX(b) ├
             ├───┤┌─────┐ │ └─┬───┬─┘└───────┘
      q82_0: ┤ H ├┤ SDG ├─■───┤ H ├───────────
             └───┘└─────┘     └───┘
      ) * 0.7071067811865476
    ])
  ]),
  SummedOp([
    0.5 * ComposedOp([
      OperatorMeasurement(ZZ) * 2.0,
      CircuitStateFn(
             ┌───┐┌───────┐┌───┐┌───────┐┌───┐
       q0_0: ┤ H ├┤ RZ(a) ├┤ X ├┤ RX(b) ├┤ H ├
             ├───┤└┬─────┬┘└─┬─┘└─┬───┬─┘└───┘
      q83_0: ┤ H ├─┤ SDG ├───■────┤ H ├───────
             └───┘ └─────┘        └───┘
      ) * 0.7071067811865476
    ]),
    -1.0 * ComposedOp([
      OperatorMeasurement(ZZ) * 2.0,
      CircuitStateFn(
             ┌───┐┌───────┐┌───┐┌───────┐
       q0_0: ┤ H ├┤ RZ(a) ├┤ X ├┤ RX(b) ├
             ├───┤└┬─────┬┘└─┬─┘└─┬───┬─┘
      q84_0: ┤ H ├─┤ SDG ├───■────┤ H ├──
             └───┘ └─────┘        └───┘
      ) * 0.7071067811865476
    ])
  ])
])
State gradient computed with the linear combination method [(-0.3535533905932737+0j), (0.7071067811865472+0j)]

有限差分勾配

他の方法とは異なり、有限差分勾配は分析値ではなく数値推定です。 この実装では、\(\epsilon \ll 1\) を使用した中央差分アプローチを採用しています。

\[\frac{\partial\langle\psi\left(\theta\right)|\hat{O}\left(\omega\right)|\psi\left(\theta\right)\rangle}{\partial\theta} \approx \frac{1}{2\epsilon} \left(\langle\psi\left(\theta+\epsilon\right)|\hat{O}\left(\omega\right)|\psi\left(\theta+\epsilon\right)\rangle - \partial\langle\psi\left(\theta-\epsilon\right)|\hat{O}\left(\omega\right)|\psi\left(\theta-\epsilon\right)\rangle\right).\]

確率勾配も同様に計算されます。

[8]:
# Convert the expectation value into an operator corresponding to the gradient w.r.t. the state parameter using
# the finite difference method.
state_grad = Gradient(grad_method='fin_diff').convert(operator=op, params=params)

# Print the operator corresponding to the gradient
print(state_grad)

# Assign the parameters and evaluate the gradient
state_grad_result = state_grad.assign_parameters(value_dict).eval()
print('State gradient computed with finite difference', state_grad_result)
ListOp([
  SummedOp([
    250000.0 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌────────────────┐┌───────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a + 1.0e-6) ├┤ RX(b) ├┤ H ├
            └───┘└────────────────┘└───────┘└───┘
      )
    ]),
    -250000.0 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌────────────────┐┌───────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a - 1.0e-6) ├┤ RX(b) ├┤ H ├
            └───┘└────────────────┘└───────┘└───┘
      )
    ]),
    -500000.0 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌────────────────┐┌───────┐
      q0_0: ┤ H ├┤ RZ(a + 1.0e-6) ├┤ RX(b) ├
            └───┘└────────────────┘└───────┘
      )
    ]),
    500000.0 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌────────────────┐┌───────┐
      q0_0: ┤ H ├┤ RZ(a - 1.0e-6) ├┤ RX(b) ├
            └───┘└────────────────┘└───────┘
      )
    ])
  ]),
  SummedOp([
    250000.0 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌────────────────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b + 1.0e-6) ├┤ H ├
            └───┘└───────┘└────────────────┘└───┘
      )
    ]),
    -250000.0 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌────────────────┐┌───┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b - 1.0e-6) ├┤ H ├
            └───┘└───────┘└────────────────┘└───┘
      )
    ]),
    -500000.0 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌────────────────┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b + 1.0e-6) ├
            └───┘└───────┘└────────────────┘
      )
    ]),
    500000.0 * ComposedOp([
      OperatorMeasurement(Z),
      CircuitStateFn(
            ┌───┐┌───────┐┌────────────────┐
      q0_0: ┤ H ├┤ RZ(a) ├┤ RX(b - 1.0e-6) ├
            └───┘└───────┘└────────────────┘
      )
    ])
  ])
])
State gradient computed with finite difference [(-0.35355339057345814+0j), (0.707106781149+0j)]

自然勾配

一次の勾配の特別なタイプとして、古典的な機械学習で有用であることが示されている自然勾配があり、これは量子の文脈では既に研究されています。この量は、量子フィッシャー情報量行列 (Quantum Fisher Information matrix, QFI) の逆行列によって「再スケーリング」された勾配を表しています。

\[QFI ^{-1} \frac{\partial\langle\psi\left(\theta\right)|\hat{O}\left(\omega\right)|\psi\left(\theta\right)\rangle}{\partial\theta}.\]

QFI の逆行列を取る代わりに、以下の問題を正則化の有無にかかわらず最小二乗ソルバーによって解くこともできます。

\[QFI x = \frac{\partial\langle\psi\left(\theta\right)|\hat{O}\left(\omega\right)|\psi\left(\theta\right)\rangle}{\partial\theta}.\]

この実装は、 L-curve corner search を用いたパラメーターの自動探索による L1 正則化と L2 正則化、および QFI の対角要素の二種類の摂動をサポートしています。

自然勾配は、勾配ベースのオプティマイザーや ODE ソルバーで、標準勾配の代わりに用いることができます。

[9]:
# Besides the method to compute the circuit gradients resp. QFI, a regularization method can be chosen:
# `ridge` or `lasso` with automatic parameter search or `perturb_diag_elements` or `perturb_diag`
# which perturb the diagonal elements of the QFI.
nat_grad = NaturalGradient(grad_method='lin_comb', qfi_method='lin_comb_full', regularization='ridge').convert(
                           operator=op, params=params)

# Assign the parameters and evaluate the gradient
nat_grad_result = nat_grad.assign_parameters(value_dict).eval()
print('Natural gradient computed with linear combination of unitaries', nat_grad_result)
Natural gradient computed with linear combination of unitaries [-2.62895551  1.31447775]

ヘシアン (二次の勾配)

Gradient フレームワークでは、4種類の二次勾配をサポートしています。

  1. 測定演算子すなわちオブザーバブル \(\hat{O}\left(\omega\right)\) の係数に対する期待値の勾配。つまり、 \(\frac{\partial^2\langle\psi\left(\theta\right)|\hat{O}\left(\omega\right)|\psi\left(\theta\right)\rangle}{\partial\omega^2}\)

  2. 状態 \(|\psi\left(\theta\right)\rangle\) のパラメーターに対する期待値の勾配。すなわち \(\frac{\partial^2\langle\psi\left(\theta\right)|\hat{O}\left(\omega\right)|\psi\left(\theta\right)\rangle}{\partial\theta^2}\)

  3. 状態 \(|\psi\left(\theta\right)\rangle\) のパラメーター に対するサンプリング確率の勾配。すなわち、 \(\frac{\partial^2 p_i}{\partial\theta^2} = \frac{\partial^2\langle\psi\left(\theta\right)|i\rangle\langle i|\psi\left(\theta\right)\rangle}{\partial\theta^2}\)

  4. 状態 \(|\psi\left(\theta\right)\rangle\) のパラメーターとれぞれ観測可能な \(\hat{O}\left(\omega\right)\), に対する期待値の勾配。すなわち \(\frac{\partial^2\langle\psi\left(\theta\right)|\hat{O}\left(\omega\right)|\psi\left(\theta\right)\rangle}{\partial\theta\partial\omega}\)

以下の例では、最初の二つのヘシアンについて説明します。残りのヘシアンは類似的に評価されます。

測定演算子のパラメーターに関する勾配

ここでも、量子状態 \(|\psi\left(\theta\right)\rangle\) と観測量としてのハミルトニアン \(H\) を定義します。そして状態とハミルトニアンを、以下のように期待値を定義するオブジェクトとしてラップします。

\[\langle\psi\left(\theta\right)|H|\psi\left(\theta\right)\rangle.\]
[10]:
# Instantiate the Hamiltonian observable
H = X

# Instantiate the quantum state with two parameters
a = Parameter('a')
b = Parameter('b')

q = QuantumRegister(1)
qc = QuantumCircuit(q)
qc.h(q)
qc.rz(a, q[0])
qc.rx(b, q[0])

# Combine the Hamiltonian observable and the state
op = ~StateFn(H) @ CircuitStateFn(primitive=qc, coeff=1.)

次に、二次の勾配を計算したいパラメーターを選びます。 タプルが与えられると、 Hessian は二つのパラメーターに関する二次の勾配を計算します。リストが与えられると、 Hessian はこれらのパラメータのタプルの全ての可能な組み合わせについて、二次の勾配を計算します。

パラメーターを固定した後、ヘシアンを評価することができます。

[11]:
# Convert the operator and the hessian target coefficients into the respective operator
hessian = Hessian().convert(operator = op, params = [a, b])

# Define the values to be assigned to the parameters
value_dict = {a: np.pi / 4, b: np.pi/4}

# Assign the parameters and evaluate the Hessian w.r.t. the Hamiltonian coefficients
hessian_result = hessian.assign_parameters(value_dict).eval()
print('Hessian \n', np.real(np.array(hessian_result)))
Hessian
 [[-7.07106781e-01  0.00000000e+00]
 [ 0.00000000e+00 -5.55111512e-17]]

状態パラメーターに関するヘシアン

[12]:
# Define parameters
params = [a, b]

# Get the operator object representing the Hessian
state_hess = Hessian(hess_method='param_shift').convert(operator=op, params=params)
# Assign the parameters and evaluate the Hessian
hessian_result = state_hess.assign_parameters(value_dict).eval()
print('Hessian computed using the parameter shift method\n', (np.array(hessian_result)))

# Get the operator object representing the Hessian
state_hess = Hessian(hess_method='lin_comb').convert(operator=op, params=params)
# Assign the parameters and evaluate the Hessian
hessian_result = state_hess.assign_parameters(value_dict).eval()
print('Hessian computed using the linear combination of unitaries method\n', (np.array(hessian_result)))

# Get the operator object representing the Hessian using finite difference
state_hess = Hessian(hess_method='fin_diff').convert(operator=op, params=params)
# Assign the parameters and evaluate the Hessian
hessian_result = state_hess.assign_parameters(value_dict).eval()
print('Hessian computed with finite difference\n', (np.array(hessian_result)))
Hessian computed using the parameter shift method
 [[-7.07106781e-01+0.j  0.00000000e+00+0.j]
 [ 0.00000000e+00+0.j -5.55111512e-17+0.j]]
Hessian computed using the linear combination of unitaries method
 [[-7.07106781e-01+0.j  0.00000000e+00+0.j]
 [ 0.00000000e+00+0.j  5.60000000e-17+0.j]]
Hessian computed with finite difference
 [[-7.07122803e-01+0.j  3.05175781e-05+0.j]
 [ 3.05175781e-05+0.j -6.10351562e-05+0.j]]

量子フィッシャー情報量 (QFI)

量子フィッシャー情報量は、入力状態 \(|\psi\rangle\) および パラメータ化されたAnsatz \(V\left(\theta\right)\) からなる、パラメータ化された量子状態 \(|\psi\left(\theta\right)\rangle = V\left(\theta\right)|\psi\rangle\) の表現能力を表す計量テンソルです。

純粋状態に対する QFI のエントリーは、以下のようになります。

\[QFI_{kl} = 4 * \text{Re}\left[\langle\partial_k\psi|\partial_l\psi\rangle-\langle\partial_k\psi|\psi\rangle\langle\psi|\partial_l\psi\rangle \right].\]

回路 QFI

パラメーター化された量子回路によって生成される量子状態の QFI の評価は、様々な方法で行うことができます。

完全な QFI の線形結合

完全な QFI を計算するために、制御ゲートの傍受だけでなく、ワーキング量子ビットも使用します。例えば Variational ansatz-based quantum simulation of imaginary time evolution を参照してください。

[13]:
# Wrap the quantum circuit into a CircuitStateFn
state = CircuitStateFn(primitive=qc, coeff=1.)

# Convert the state and the parameters into the operator object that represents the QFI
qfi = QFI(qfi_method='lin_comb_full').convert(operator=state, params=params)
# Define the values for which the QFI is to be computed
values_dict = {a: np.pi / 4, b: 0.1}

# Assign the parameters and evaluate the QFI
qfi_result = qfi.assign_parameters(values_dict).eval()
print('full QFI \n', np.real(np.array(qfi_result)))
full QFI
 [[ 1.0000000e+00 -2.0659798e-16]
 [-2.0659798e-16  5.0000000e-01]]

ブロック対角と対角近似

QFI のブロック対角化と対角近似はそれぞれ、追加のワーキング量子ビット無しで計算することができます。この実装では、 Pauli 回転と非パラメータ化ゲートへの展開が必要です。

[14]:
# Convert the state and the parameters into the operator object that represents the QFI
# and set the approximation to 'block_diagonal'
qfi = QFI('overlap_block_diag').convert(operator=state, params=params)

# Assign the parameters and evaluate the QFI
qfi_result = qfi.assign_parameters(values_dict).eval()
print('Block-diagonal QFI \n', np.real(np.array(qfi_result)))

# Convert the state and the parameters into the operator object that represents the QFI
# and set the approximation to 'diagonal'
qfi = QFI('overlap_diag').convert(operator=state, params=params)

# Assign the parameters and evaluate the QFI
qfi_result = qfi.assign_parameters(values_dict).eval()
print('Diagonal QFI \n', np.real(np.array(qfi_result)))
Block-diagonal QFI
 [[1.  0. ]
 [0.  0.5]]
Diagonal QFI
 [[1.  0. ]
 [0.  0.5]]

応用例: 勾配ベース最適化による VQE

追加のインポート

[15]:
# Execution Imports
from qiskit import Aer
from qiskit.utils import QuantumInstance

# Algorithm Imports
from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import CG

Gradient フレームワークは、勾配ベースの VQE にも利用できます。まず、ハミルトニアンと波動関数のansatzを初期化します。

[16]:
from qiskit.opflow import I, X, Z
from qiskit.circuit import QuantumCircuit, ParameterVector
from scipy.optimize import minimize

# Instantiate the system Hamiltonian
h2_hamiltonian = -1.05 * (I ^ I) + 0.39 * (I ^ Z) - 0.39 * (Z ^ I) - 0.01 * (Z ^ Z) + 0.18 * (X ^ X)

# This is the target energy
h2_energy = -1.85727503

# Define the Ansatz
wavefunction = QuantumCircuit(2)
params = ParameterVector('theta', length=8)
it = iter(params)
wavefunction.ry(next(it), 0)
wavefunction.ry(next(it), 1)
wavefunction.rz(next(it), 0)
wavefunction.rz(next(it), 1)
wavefunction.cx(0, 1)
wavefunction.ry(next(it), 0)
wavefunction.ry(next(it), 1)
wavefunction.rz(next(it), 0)
wavefunction.rz(next(it), 1)

# Define the expectation value corresponding to the energy
op = ~StateFn(h2_hamiltonian) @ StateFn(wavefunction)

これで、 VQEGradientNaturalGradient のどちらを使うかを選択し、量子回路を実行するための QuantumInstance を定義して、アルゴリズムを実行することができます。

[17]:
grad = Gradient(grad_method='lin_comb')

qi_sv = QuantumInstance(Aer.get_backend('aer_simulator_statevector'),
                        shots=1,
                        seed_simulator=2,
                        seed_transpiler=2)

#Conjugate Gradient algorithm
optimizer = CG(maxiter=50)

# Gradient callable
vqe = VQE(wavefunction, optimizer=optimizer, gradient=grad, quantum_instance=qi_sv)

result = vqe.compute_minimum_eigenvalue(h2_hamiltonian)
print('Result:', result.optimal_value, 'Reference:', h2_energy)
Result: -0.8800000000000001 Reference: -1.85727503
[18]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
QiskitNone
Terra0.17.4
Aer0.8.2
IgnisNone
AquaNone
IBM Q ProviderNone
System information
Python3.8.8 (default, Apr 13 2021, 12:59:45) [Clang 10.0.0 ]
OSDarwin
CPUs2
Memory (Gb)12.0
Fri May 28 09:42:47 2021 EDT

This code is a part of Qiskit

© Copyright IBM 2017, 2021.

This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.

Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.

[ ]: