주 콘텐츠로 건너뛰기

연산자 클래스 개요

패키지 버전

이 페이지의 코드는 다음 요구 사항을 사용하여 개발되었습니다. 이 버전 이상을 사용하길 권장합니다.

qiskit[all]~=2.3.0

Qiskit에서 양자 연산자는 quantum_info 모듈의 클래스를 사용하여 표현됩니다. 가장 중요한 연산자 클래스는 SparsePauliOp로, 일반적인 양자 연산자를 파울리 문자열의 선형 결합으로 표현합니다. SparsePauliOp는 양자 관측량을 표현하는 데 가장 일반적으로 사용되는 클래스입니다. 이 페이지의 나머지 부분에서는 SparsePauliOp 및 기타 연산자 클래스의 사용 방법을 설명합니다.

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit
import numpy as np
from qiskit.quantum_info.operators import Operator, Pauli, SparsePauliOp

SparsePauliOp

SparsePauliOp 클래스는 파울리 문자열의 선형 결합을 표현합니다. SparsePauliOp를 초기화하는 방법은 여러 가지가 있지만, 가장 유연한 방법은 다음 코드 셀에서 시연하는 것처럼 from_sparse_list 메서드를 사용하는 것입니다. from_sparse_list(pauli_string, qubit_indices, coefficient) 삼중항의 목록을 받습니다.

op1 = SparsePauliOp.from_sparse_list(
[("ZX", [1, 4], 1.0), ("YY", [0, 3], -1 + 1j)], num_qubits=5
)
op1
SparsePauliOp(['XIIZI', 'IYIIY'],
coeffs=[ 1.+0.j, -1.+1.j])

SparsePauliOp는 다음 코드 셀에서 시연하는 것처럼 산술 연산을 지원합니다.

op2 = SparsePauliOp.from_sparse_list(
[("XXZ", [0, 1, 4], 1 + 2j), ("ZZ", [1, 2], -1 + 1j)], num_qubits=5
)

# Addition
print("op1 + op2:")
print(op1 + op2)
print()
# Multiplication by a scalar
print("2 * op1:")
print(2 * op1)
print()
# Operator multiplication (composition)
print("op1 @ op2:")
print(op1 @ op2)
print()
# Tensor product
print("op1.tensor(op2):")
print(op1.tensor(op2))
op1 + op2:
SparsePauliOp(['XIIZI', 'IYIIY', 'ZIIXX', 'IIZZI'],
coeffs=[ 1.+0.j, -1.+1.j, 1.+2.j, -1.+1.j])

2 * op1:
SparsePauliOp(['XIIZI', 'IYIIY'],
coeffs=[ 2.+0.j, -2.+2.j])

op1 @ op2:
SparsePauliOp(['YIIYX', 'XIZII', 'ZYIXZ', 'IYZZY'],
coeffs=[ 1.+2.j, -1.+1.j, -1.+3.j, 0.-2.j])

op1.tensor(op2):
SparsePauliOp(['XIIZIZIIXX', 'XIIZIIIZZI', 'IYIIYZIIXX', 'IYIIYIIZZI'],
coeffs=[ 1.+2.j, -1.+1.j, -3.-1.j, 0.-2.j])

Pauli

Pauli 클래스는 집합 {+1,i,1,i}\set{+1, i, -1, -i}에서 선택된 선택적 위상 계수를 가진 단일 파울리 문자열을 표현합니다. Pauli{"I", "X", "Y", "Z"} 집합의 문자로 구성된 문자열을 전달하여 초기화할 수 있으며, 선택적으로 위상 계수를 표현하기 위해 {"", "i", "-", "-i"} 중 하나를 접두사로 붙일 수 있습니다.

op1 = Pauli("iXX")
op1
Pauli('iXX')

다음 코드 셀은 일부 속성 및 메서드의 사용을 시연합니다.

print(f"Dimension of {op1}: {op1.dim}")
print(f"Phase of {op1}: {op1.phase}")
print(f"Matrix representation of {op1}: \n {op1.to_matrix()}")
Dimension of iXX: (4, 4)
Phase of iXX: 3
Matrix representation of iXX:
[[0.+0.j 0.+0.j 0.+0.j 0.+1.j]
[0.+0.j 0.+0.j 0.+1.j 0.+0.j]
[0.+0.j 0.+1.j 0.+0.j 0.+0.j]
[0.+1.j 0.+0.j 0.+0.j 0.+0.j]]

Pauli 객체는 수반(adjoint) 결정, 다른 Pauli와의 (반)교환 여부 확인, 다른 Pauli와의 내적 계산 등 연산자를 조작하는 다양한 메서드를 보유하고 있습니다. 자세한 내용은 API 문서를 참고하세요.

Operator

Operator 클래스는 일반적인 선형 연산자를 표현합니다. SparsePauliOp와 달리, Operator는 선형 연산자를 밀집 행렬로 저장합니다. 밀집 행렬을 저장하는 데 필요한 메모리는 Qubit 수에 따라 지수적으로 증가하기 때문에, Operator 클래스는 소수의 Qubit에만 사용하기에 적합합니다.

Numpy 배열을 직접 전달하여 연산자의 행렬을 저장하는 방식으로 Operator를 초기화할 수 있습니다. 예를 들어, 다음 코드 셀은 2-Qubit 파울리 XX 연산자를 생성합니다:

XX = Operator(
np.array(
[
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0],
[1, 0, 0, 0],
]
)
)
XX
Operator([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
[0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]],
input_dims=(2, 2), output_dims=(2, 2))

연산자 객체는 기저 행렬과 서브시스템의 입력 및 출력 차원을 저장합니다.

  • data: 기저 Numpy 배열에 접근하려면 Operator.data 속성을 사용할 수 있습니다.
  • dims: 연산자의 전체 입력 및 출력 차원을 반환하려면 Operator.dim 속성을 사용할 수 있습니다. 참고: 출력은 기저 행렬의 형태와 반대인 (input_dim, output_dim) 튜플로 반환됩니다.
XX.data
array([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
[0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]])
input_dim, output_dim = XX.dim
input_dim, output_dim
(4, 4)

연산자 클래스는 또한 서브시스템 차원을 추적하며, 이는 연산자들을 합성하는 데 사용될 수 있습니다. input_dimsoutput_dims 함수를 사용하여 이에 접근할 수 있습니다.

2N2^N x 2M2^M 연산자의 경우, 입력 및 출력 차원은 자동으로 M-Qubit 및 N-Qubit으로 가정됩니다:

op = Operator(np.random.rand(2**1, 2**2))
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (2, 2)
Output dimensions: (2,)

입력 행렬이 Qubit 서브시스템으로 나누어지지 않는 경우, 단일 Qubit 연산자로 저장됩니다. 예를 들어, 6×66\times6 행렬의 경우:

op = Operator(np.random.rand(6, 6))
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (6,)
Output dimensions: (6,)

새 연산자를 초기화할 때 입력 및 출력 차원을 수동으로 지정할 수도 있습니다:

# Force input dimension to be (4,) rather than (2, 2)
op = Operator(np.random.rand(2**1, 2**2), input_dims=[4])
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (4,)
Output dimensions: (2,)
# Specify system is a qubit and qutrit
op = Operator(np.random.rand(6, 6), input_dims=[2, 3], output_dims=[2, 3])
print("Input dimensions:", op.input_dims())
print("Output dimensions:", op.output_dims())
Input dimensions: (2, 3)
Output dimensions: (2, 3)

input_dimsoutput_dims 함수를 사용하여 서브시스템의 하위 집합에 대한 입력 또는 출력 차원만 추출할 수도 있습니다:

print("Dimension of input system 0:", op.input_dims([0]))
print("Dimension of input system 1:", op.input_dims([1]))
Dimension of input system 0: (2,)
Dimension of input system 1: (3,)

다음 단계

권장 사항