Japanese
Languages
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

注釈

このページは tutorials/simulators/7_matrix_product_state_method.ipynb から生成されました。

行列積状態を用いたシミュレーション法

シミュレーション方法

AerSimulator には、statevectorstabilizerextended_stabilizermatrix_product_state などのいくつかのシミュレーション・メソッドがあります。 それぞれが量子回路の内部表現と、量子演算を処理するために使用されるアルゴリズムを決定します。 それぞれに長所と短所があり、最良の方法を選ぶには調査が必要です。 このチュートリアルでは、行列積状態を用いたシミュレーション・メソッド に焦点を当てます。

行列積状態を用いたシミュレーション法

このシミュレーション方法は matrix product states の概念に基づいています。 この構造は、最初に Vidal の Efficient classical simulation of slightly entangled quantum computations*(https://arxiv.org/abs/quant-ph/0301063) で提案されました。構造をより詳細に説明する論文として、例えば Schollwoeck の *The density-matrix renormalization group in the age of matrix product states (https://arxiv.org/abs/1008.3477) があります。

純粋な量子状態は通常、状態ベクトルとして記述されます。 式で書くと、 \(|\psi\rangle = \sum_{i_1=0}^1 {\ldots} \sum_{i_n=0}^1 c_{i_1 \ldots i_n} |i_i\rangle {\otimes} {\ldots} |i_n\rangle\) です。

状態ベクトル表現は、実際の回路に関係なく、指数サイズ表現を伴います。 この表現で動作するすべての量子ゲートには、指数時間と指数メモリが必要です。

行列積状態(Matrix Product State、MPS)表示は、形式: \(\Gamma^{[1]} \lambda^{[1]} \Gamma^{[2]} \lambda^{[2]}\ldots \Gamma^{[1]} \lambda^{[n-1]} \Gamma^{[n]}\) にてローカル表示を提供します。 \(c_{i_1 \ldots i_n}\) に含まれるすべての情報を、MPS表現から生成できるようにします。

すべての \(\Gamma^{[i]}\) は qubit \(i\) を表す複素数のテンソルです。 \(\lambda^{[i]}\) は実数の行列で、量子ビット \(i\)\(i+1\) の振幅を正規化するために使用されます。 単一量子ビットゲートは、該当するテンソルでのみ動作します。

2量子ビットゲートは連続した量子ビット \(i\) and \(i+1\) に作用します。これには \(\lambda^{[i-1]}\), \(\Gamma^{[i-1]}\), \(\lambda^{[i]}\), \(\Gamma^{[i+1]}\) および \(\lambda^{[i+1]}\) のテンソル縮約が含まれ、単一のテンソルが作成されます。ゲートにはこのテンソルが適用され、次に元の構造にデコンポーズ(decompose) されます。この操作は各テンソルの大きさを増やすかも知れません。2つの量子ビットが連続していない場合には、swap ゲートをいくつか適用し2量子ビットが連続するようにし、再び swap を適応して元に戻します。

最悪の場合、テンソルは指数関数的に成長する可能性があります。 しかし、構造全体の大きさは、 ‘多くの’ 2量子ビットゲートを持たない回路では ‘小さい’ ままです。これにより、比較的 ‘低い’ もつれの回路では、はるかに効率的な演算が可能になります。 他の方法ではなく、この方法を使うタイミングを特徴づけることは、現在の研究の対象です。

行列積状態シミュレーション方法を利用する

行列積状態シミュレーション・メソッドは、シミュレーション・メソッドを設定することによって AerSimulator 内で呼び出されます。 それ以外のすべての操作は、次の例のように、 AerSimulator 自体によって制御されます。

[1]:
import numpy as np

# Import Qiskit
from qiskit import QuantumCircuit, transpile
from qiskit.providers.aer import AerSimulator

# Construct quantum circuit
circ = QuantumCircuit(2, 2)
circ.h(0)
circ.cx(0, 1)
circ.measure([0,1], [0,1])

# Select the AerSimulator from the Aer provider
simulator = AerSimulator(method='matrix_product_state')

# Run and get counts, using the matrix_product_state method
tcirc = transpile(circ, simulator)
result = simulator.run(tcirc).result()
counts = result.get_counts(0)
counts
[1]:
{'11': 515, '00': 509}

回路内部の状態ベクトルを見るには、save_statevector 命令を使います。完全な内部のMPS構造を返すには、save_matrix_product_state 命令も使用できます。

[2]:
circ = QuantumCircuit(2, 2)
circ.h(0)
circ.cx(0, 1)

# Define a snapshot that shows the current state vector
circ.save_statevector(label='my_sv')
circ.save_matrix_product_state(label='my_mps')
circ.measure([0,1], [0,1])

# Execute and get saved data
tcirc = transpile(circ, simulator)
result = simulator.run(tcirc).result()
data = result.data(0)

#print the result data
data
[2]:
{'counts': {'0x0': 494, '0x3': 530},
 'my_sv': array([0.70710678+0.j, 0.        +0.j, 0.        +0.j, 0.70710678+0.j]),
 'my_mps': ([(array([[1.-0.j, 0.-0.j]]), array([[0.-0.j, 1.-0.j]])),
   (array([[1.-0.j],
           [0.-0.j]]),
    array([[0.-0.j],
           [1.-0.j]]))],
  [array([0.70710678, 0.70710678])])}

行列積状態シミュレーション方法を使用した実行回路は、他の方法と比較して高速である可能性があります。 しかし、実行中に状態ベクトルを生成した場合、状態ベクトルへの変換は もちろんメモリーと時間の指数関数的なものです したがって我々はこの方法を使う恩恵を受けることはできません。 完全な状態ベクトルを出力する必要のない操作のみを行うことで利益を得ることができます。 例えば、回路を動かしてから測定する場合があげられます。以下の回路は200量子ビットです。 これらすべての量子ビットを含む EPR 状態 を作成します。 この状態は非常にエンタングルしていますが、実質的には2つの状態しか存在しないため、行列積状態法によってうまく処理されます。

これよりも多くの量子ビットを扱うことができますが、実行には数分かかる場合があります。 500量子ビットで同じような回路を実行してみてください! または、1000など (待っている間にコーヒーを1杯飲むことができます)。

[3]:
num_qubits = 50
circ = QuantumCircuit(num_qubits, num_qubits)

# Create EPR state
circ.h(0)
for i in range (0, num_qubits-1):
    circ.cx(i, i+1)

# Measure
circ.measure(range(num_qubits), range(num_qubits))

tcirc = transpile(circ, simulator)
result = simulator.run(tcirc).result()
print("Time taken: {} sec".format(result.time_taken))
result.get_counts()
Time taken: 0.31022214889526367 sec
[3]:
{'11111111111111111111111111111111111111111111111111': 548,
 '00000000000000000000000000000000000000000000000000': 476}
[4]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
Qiskit0.25.0
Terra0.17.0
Aer0.8.0
Ignis0.6.0
Aqua0.9.0
IBM Q Provider0.12.2
System information
Python3.8.8 | packaged by conda-forge | (default, Feb 20 2021, 16:22:27) [GCC 9.3.0]
OSLinux
CPUs8
Memory (Gb)31.38858413696289
Tue Apr 20 15:22:58 2021 UTC

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.

[ ]: