🐈

振幅エンコーディング (3)

2022/10/16に公開

制御振幅エンコーディング

前回は、データ木構造を用いた振幅エンコーディングについて記載しました。

VQLS(Variational Quantum Linear Solver)でこれを用いるにあたり、制御振幅エンコーディング回路を実装する必要があります。

VQLSについて日本語の参考になる解説記事がありますので、VQLSについてはそちらを参照ください。


制御ビットの指定

例として、データ木の一番深いところで考えます。

疑似コードのとおり、制御回転ゲート CRy および CCXCCZ を適用する際のフラグとして制御ビットを利用することにしました。

CRy について、RyCX も実行されてしまいますが、k bit目が反転していない限り元に戻ります。

# v_i            : エンコードしたいベクトルの要素
# multi_flag     : (1/pi)*arccos(v_i)を二進数表示の計算のためのフラグ
# msb_index      : 最上位量子ビットのインデックス
# si_offset      : m bit精度近似計算のための、データレジスタの開始インデックス
# depth          : データ木構造の深さ
# node_prob_list : データ木構造におけるノードの確率をリストにしたもの
# upper_nd_index : データ木構造における現ノードの、一つ上の深さのノード(上位ビット)のインデックス

# Ry Rotation 
for k in range(len(multi_flag)):
    if multi_flag[k] == 1:
        qc.ccx(controled_bit_index, (msb_index-si_offset) - (depth-1), k)
        # CRy
        qc.ry(0.5*   (np.pi / np.power(2, (k+1)*multi_flag[k]) *2), (msb_index-si_offset) - depth)
        qc.cx(k, (msb_index-si_offset) - depth)
        qc.ry(0.5* - (np.pi / np.power(2, (k+1)*multi_flag[k]) *2), (msb_index-si_offset) - depth)
        qc.cx(k, (msb_index-si_offset) - depth)

if (depth == len(node_prob_list)-1) and (np.sign(node_prob_list[depth][upper_nd_index*2 + 1]) < 0):
    # if depth is the last, and amplitude of |k>|1> is negative, you should consider sign of vector
    # apply to only |1> state
    qc.ccz(controled_bit_index, (msb_index-si_offset) - (depth-1), (msb_index-si_offset) - depth)
if (depth == len(node_prob_list)-1) and (np.sign(node_prob_list[depth][upper_nd_index*2]) < 0):
    qc.ccx(controled_bit_index, (msb_index-si_offset) - (depth-1), (msb_index-si_offset) - depth)
    qc.ccz(controled_bit_index, (msb_index-si_offset) - (depth-1), (msb_index-si_offset) - depth)
    qc.ccx(controled_bit_index, (msb_index-si_offset) - (depth-1), (msb_index-si_offset) - depth)

実装 (Qiskit)

  • 制御量子ビット(最上位量子ビット)が 0 の場合

      # Input vector
      tgt_vec = np.array([-2, -2, 0, -1, 3, -1, 0, -2])
      norm_vec = normalize(tgt_vec)
      node_prob_list = gen_node_prob_list(norm_vec) 
    
      # Calc Quantum Circuit property
      probamp_si_offset = 1
      mbit_precison = 16
      n = int(np.log2(np.size(norm_vec)-1)) + 1
      # Initialize Quantum Circuit
      qc = QuantumCircuit()
      qr = QuantumRegister(probamp_si_offset + n + mbit_precison)
      qc.add_register(qr)   
    
      # X gate to Control-bit for debugging
      # Do nothing
      # Apply controlled Probabilistic Amplitude Encoding
      qc = controled_prob_amp_encoding_3qubit(qc, 0, probamp_si_offset, norm_vec, node_prob_list, mbit_precison)    
    
      # Simulate State
      print("---------------- State simulation -----------------")
      print("tgt_vec(normalized): ", norm_vec)
      state = sim_state(qc)
      print("---------------------------------------------------")
    
    ---------------- State simulation -----------------
    tgt_vec(normalized):  [-0.41702883 -0.41702883  0.         -0.20851441  0.62554324 -0.20851441
      0.         -0.41702883]
    1.0*|00000000000000000000> + 4.16333634234434e-16*I*|00000000000000000000> + 1.67919913975003e-17*|00010000000000000000> + 1.30770226682234e-21*I*|00010000000000000000> - 1.34877475860597e-17*|00100000000000000000> - 3.7722833377141e-33*I*|00100000000000000000> - 9.37236364387668e-35*|00110000000000000000> - 2.50144392150061e-38*I*|00110000000000000000> - 2.12455859514543e-17*|01000000000000000000> - 7.48377201431772e-33*I*|01000000000000000000> - 3.3083292814181e-34*|01010000000000000000> + 7.95954099103817e-38*I*|01010000000000000000> + 9.78271983161075e-34*|01100000000000000000> - 1.11724190190601e-49*I*|01100000000000000000> - 3.05971458325977e-50*|01110000000000000000> - 4.81651011585083e-55*I*|01110000000000000000>
    ---------------------------------------------------
    
  • 制御量子ビット(最上位量子ビット)が 1 の場合

    # Input vector
    tgt_vec = np.array([-2, -2, 0, -1, 3, -1, 0, -2])
    norm_vec = normalize(tgt_vec)
    node_prob_list = gen_node_prob_list(norm_vec)
    
    # Calc Quantum Circuit property
    probamp_si_offset = 1
    mbit_precison = 16
    n = int(np.log2(np.size(norm_vec)-1)) + 1
    # Initialize Quantum Circuit
    qc = QuantumCircuit()
    qr = QuantumRegister(probamp_si_offset + n + mbit_precison)
    qc.add_register(qr)
    
    # X gate to Control-bit for debugging
    qc.x(probamp_si_offset + n + mbit_precison-1)
    # Apply controlled Probabilistic Amplitude Encoding
    qc = controled_prob_amp_encoding_3qubit(qc, 0, probamp_si_offset, norm_vec, node_prob_list, mbit_precison)
    
    # Simulate State
    print("---------------- State simulation -----------------")
    print("tgt_vec(normalized): ", norm_vec)
    state = sim_state(qc)
    print("---------------------------------------------------")
    
    ---------------- State simulation -----------------
    tgt_vec(normalized):  [-0.41702883 -0.41702883  0.         -0.20851441  0.62554324 -0.20851441
      0.         -0.41702883]
    -0.417080686523715*|10000000000000000000> - 2.52581891030085e-16*I*|10000000000000000000> - 0.417080686523715*|10010000000000000000> - 2.7803905168812e-16*I*|10010000000000000000> - 2.63398908107789e-18*|10100000000000000000> - 9.1066950267484e-34*I*|10100000000000000000> - 0.208500420384733*|10110000000000000000> - 1.09584438270859e-16*I*|10110000000000000000> + 0.625526498858582*|11000000000000000000> + 2.95460030351555e-16*I*|11000000000000000000> - 0.20844353146532*|11010000000000000000> - 1.37724091954937e-16*I*|11010000000000000000> + 4.75898859798235e-18*|11100000000000000000> + 1.35457613644109e-18*I*|11100000000000000000> - 0.416992649783176*|11110000000000000000> - 2.48625173688326e-16*I*|11110000000000000000>
    ---------------------------------------------------
    

要改善事項

  • m bit精度近似計算のデータレジスタ(m qubits)のアドレス指定を可変にする

参考文献

Discussion