量子状態
量子状態は量子コンピューティングにおいて重要な要素です。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