量子状態
量子状態は量子コンピューティングにおいて重要な要素です。QURI Partsでの標準的な使い方についてここで説明します。
前提条件
このチュートリアルで使用するQURI Partsモジュール:
quri-parts-circuit
,quri-parts-core
以下のようにインストールすることができます:
!pip install quri-parts
量子状態クラスとquantum_state
関数の一覧
QURI Partsの量子状態クラスの一覧です:
- ComputationalBasisState (source)
- GeneralCircuitQuantumState (source)
- QuantumStateVector (source)
- ParametricCircuitQuantumState (source)
- ParametricQuantumStateVector (source)
名前の通り、各々のクラスは量子状態を記述する独自の方法を持っています。それらがどのように働くのかをみてみましょう。最後の二つの状態はパラメータ付き回路を内部で使っているため説明しません。パラメータ付き回路と状態に関するチュートリアルを参照してください。
量子状態を自動で構築してくれるquantum_state
関数があるため、量子状態クラスの全ての名前を覚える必要はありません。quantum_state
関数は量子ビットの数と、キーワード引数として(bits
,circuit
,vector
)のサブセットをとります。ここでは、異なる入力の組み合わせの出力タイプを並べます。
-
パラメータなし状態:
- quantum_state(n_qubits)
ComputationalBasisState
- quantum_state(n_qubits, bits)
ComputationalBasisState
- quantum_state(n_qubits, circuit)
GeneralCircuitQuantumState
- quantum_state(n_qubits, vector)
QuantumStateVector
- quantum_state(n_qubits, bits, circuit)
GeneralCircuitQuantumState
- quantum_state(n_qubits, vector, circuit)
QuantumStateVector
- quantum_state(n_qubits)
-
パラメータ付き状態
- quantum_state(n_qubits, parametric_circuit)
ParametricCircuitQuantumState
- quantum_state(n_qubits, bits, parametric_circuit)
ParametricCircuitQuantumState
- quantum_state(n_qubits, vector, parametric_circuit)
ParametricQuantumStateVector
- quantum_state(n_qubits, parametric_circuit)
次に、これら全ての量子状態オブジェクトを紹介します。
CircuitQuantumState
CircuitQuantumState
は、状態を回路に適用させることによって生成される量子状態を表現するクラスのためのインターフェースです。
ComputationalBasisState
と GeneralCircuitQuantumState
はCircuitQuantumState
の具体的なインスタンスです。
ComputationalBasisState (計算基底状態)
ComputationalBasisState
は計算基底状態を表します。n_qubits
、bits
を含み、int
とphase
で表現されます。計算状態を設定するbits
キーワードはリトルエンディアンの慣例に従っていることに注意してください。例えば、状態bits = 0b10
は、番目の量子ビット計算基底の状態が、番目の量子ビットがの計算基底状態を表しており、例えば、状態(QURI Partsでは番目の量子ビットが右にきます)の計算基底状態は、状態にパウリゲートを適用させた結果として与えられた状態としても考えられます。
from quri_parts.core.state import quantum_state, ComputationalBasisState
cb_state = quantum_state(5, bits=0b10101)
print(cb_state)
# Or equivalently:
# cb_state = ComputationalBasisState(5, bits=0b10101)
# output
ComputationalBasisState(qubit_count=5, bits=0b10101, phase=0π/2)
ComputationalBasisState
はいくつかのプロパティとメソッドを持っています:
from quri_parts.circuit import X
print("(ComputationalBasisState)")
# Bits
print("bits:", bin(cb_state.bits))
# Phase
print("phase:", cb_state.phase)
# Create a new state with a Pauli gate applied
pauli_added_state = cb_state.with_pauli_gate_applied(X(0))
print("new state:\n", pauli_added_state)
# output
(ComputationalBasisState)
bits: 0b10101
phase: 0.0
new state:
ComputationalBasisState(qubit_count=5, bits=0b10100, phase=0π/2)
GeneralCircuitQuantumState
量子回路オブジェクトを指定することで、GeneralCircuitQuantumState
を作成することができます。
from quri_parts.circuit import QuantumCircuit
circuit = QuantumCircuit(2)
circuit.add_Z_gate(0)
circuit.add_H_gate(1)
# A quantum state of 2 qubits with a given circuit (i.e. C|00> where C is the ciruict)
circuit_state = quantum_state(2, circuit=circuit)
# Or equivalently,
# from quri_parts.core.state import GeneralCircuitQuantumState
# circuit_state = GeneralCircuitQuantumState(2, circuit)
# A quantum state of 2 qubits with an empty circuit (i.e. |00>)
# circuit_state = GeneralCircuitQuantumState(2)
以前のセクションで紹介したComputationalBasisState
もCircuitQuantumState
であることに注意してください。計算基底状態は、常にXゲートを状態に適用することで構築することができるからです。
CircuitQuantumState
はいくつかのプロパティとメソッドを持っています:
from quri_parts.circuit import CNOT
print("(circuit_state)")
# Get how many qubits this state is for.
print("qubit_count:", circuit_state.qubit_count)
# Get the circuit of the state. This returns an immutable circuit.
print("circuit:", circuit_state.circuit)
# Create a new state with some new gates added.
gate_added_state = circuit_state.with_gates_applied([X(1), CNOT(1, 0)])
print("original circuit len:", len(circuit_state.circuit.gates))
print("new circuit len:", len(gate_added_state.circuit.gates))
# output
(circuit_state)
qubit_count: 2
circuit: <quri_parts.circuit.circuit.ImmutableQuantumCircuit object at 0x10d789370>
original circuit len: 2
new circuit len: 4
量子回路をComputationalBasisState
に適用させることで作成される状態はもはやComputationalBasisState
ではなく一般的なGeneralCircuitQuantumState
であることに注意してください。
comp_basis_superposition
を使用すると、二つのComputationalBasisState
の重ね合わせを作成できます。出力はGeneralCircuitQuantumState
になります。QURI Partsでは、二つの計算基底状態との重ねあわせは
で定義されます。
from math import pi
from quri_parts.core.state import comp_basis_superposition
new_state = cb_state.with_gates_applied([CNOT(0, 1)])
print("new state:\n", new_state)
cb_state1 = quantum_state(2, bits=0b00)
cb_state2 = quantum_state(2, bits=0b11)
superposition_state = comp_basis_superposition(cb_state1, cb_state2, theta=-pi/4, phi=0.0)
print("superposition state circuit:\n", superposition_state.circuit.gates)
# output
new state:
GeneralCircuitQuantumState(n_qubits=5, circuit=<quri_parts.circuit.circuit.ImmutableQuantumCircuit object at 0x1079e3c70>)
superposition state circuit:
(QuantumGate(name='PauliRotation', target_indices=(0, 1), control_indices=(), classical_indices=(), params=(1.5707963267948966,), pauli_ids=(1, 1), unitary_matrix=()), QuantumGate(name='RZ', target_indices=(0,), control_indices=(), classical_indices=(), params=(-1.5707963267948966,), pauli_ids=(), unitary_matrix=()))
QuantumStateVector
QuantumStateVector
は状態ベクトルで定義された状態を表し、適用する回路は任意です。
from quri_parts.core.state import QuantumStateVector
import numpy as np
circuit = QuantumCircuit(2, gates=[X(0)])
sv = quantum_state(2, vector=np.array([1.0, 0.0, 0.0, 0.0]), circuit=circuit)
# Or equivalently,
# sv = QuantumStateVector(2, [1.0, 0.0, 0.0, 0.0], circuit)
QuantumStateVector
もいくつかのプロパティを持っています:
print("(quantum state vector)")
# Get how many qubits this state is for.
print("qubit_count:", sv.qubit_count)
# Get the circuit of the state. This returns an immutable circuit.
print("circuit:", sv.circuit)
# Get the vector of the state.
print("vector:", sv.vector)
# Create a new state with some new gates added.
gate_added_state = sv.with_gates_applied([X(1), CNOT(1, 0)])
print("original circuit len:", len(sv.circuit.gates))
print("new circuit len:", len(gate_added_state.circuit.gates))
# output
(quantum state vector)
qubit_count: 2
circuit: <quri_parts.circuit.circuit.ImmutableQuantumCircuit object at 0x10d77e130>
vector: [1.+0.j 0.+0.j 0.+0.j 0.+0.j]
original circuit len: 1
new circuit len: 3
QuantumStateVector
は回路を保持していますが、.vector
属性は回路によって更新された状態ベクトルを返しません。更新されたものが欲しい 場合は、quri-parts-qulacs
モジュールのevaluate_state_to_vector
を使用することを考慮してください。さらに詳しいことはシミュレータ チュートリアルを参照してください。
QURI Parsの量子状態のクラスは常にイミュータブルです。作成された量子状態オブジェクトは修正することができません。
回路を状態に適用
QURI Partsには、量子回路を既存の状態に適用するための便利なヘルパー関数apply_circuit
が用意されています。自動的に正確な量子状態のタイプを変換します。
from quri_parts.core.state import apply_circuit
# Apply a circuit to a ComputationalBasisState.
new_state1 = apply_circuit(
QuantumCircuit(2, gates=[X(1)]), cb_state
) # GeneralCircuitQuantumState
# Apply a circuit to a GeneralCircuitQuantumState.
new_state2 = apply_circuit(
QuantumCircuit(2, gates=[X(1)]), circuit_state
) # GeneralCircuitQuantumState
# Apply a circuit to a QuantumStateVector.
new_state3 = apply_circuit(QuantumCircuit(2, gates=[X(1)]), sv) # QuantumStateVector