주 콘텐츠로 건너뛰기

ansatz

Victoria Lipinska가 ansatz가 무엇이며, 변분 양자 고유솔버(VQE) 맥락에서 왜 중요한지 설명하는 영상을 시청해 봅니다.

참고문헌

위 영상에서 참조된 논문은 다음과 같습니다.

ansatz 코드

이전 강의에서는 관심 분자의 에너지를 기술하는 Hamiltonian 을 생성하고, 이를 양자 컴퓨터에 유용한 형식으로 매핑했습니다. VQE는 변분 Circuit 을 사용하여 양자 상태를 준비합니다. 그런 다음 이러한 상태를 사용하여 Hamiltonian 의 기댓값(에너지)을 결정합니다. 변분 Circuit의 매개변수는 계산이 최솟값 기댓값으로 수렴할 때까지 변화됩니다. 양자 화학 맥락에서 이는 바닥 상태 에너지여야 합니다. 이 강의에서는 변분 Circuit, 즉 ansatz (독일어로 "접근" 또는 "방법"을 의미)에 중점을 둡니다. 이 강의에서 다음을 학습합니다

  • Circuit 라이브러리에서 사용 가능한 미리 만들어진 ansatz 세트
  • ansatz의 특징을 지정하거나 수정하는 방법
  • 자신만의 ansatz를 구축하는 방법
  • 좋은 ansatz와 나쁜 ansatz의 예시

Qiskit Circuit 라이브러리에는 ansatz로 사용할 수 있는 여러 범주의 Circuit이 있습니다. 여기서는 2-local Circuit(한 번에 최대 두 개의 Qubit에 작용하는 Gate로 구성된 Circuit)에 대한 논의로 제한합니다. Efficient SU2 는 일반적으로 사용되는 ansatz입니다.

efficient_su_2 Circuit은 SU(2)(차수 2의 특수 유니터리 그룹, 예: Pauli 회전 Gate)로 생성되는 단일 Qubit 연산 계층과 CX 얽힘 계층으로 구성됩니다. 이는 VQE와 같은 변분 양자 알고리즘과 양자 기계 학습(QML)의 분류 Circuit에서 유용할 수 있는 휴리스틱 패턴입니다.

두 가지 종류의 SU(2) Gate(예: rx와 y)를 사용하는 4-Qubit efficient_su2 Circuit 예제로 시작합니다. 또한 얽힘 방식과 반복 횟수를 지정합니다. Circuit을 단순히 .draw()하면 상당히 추상적인 표현을 얻게 됩니다. 더 이해하기 쉬운 Circuit 다이어그램은 .decompose().draw()를 사용하여 얻을 수 있으며, 여기서는 output = "mpl"을 사용합니다.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit.circuit.library import efficient_su2

SU2_ansatz = efficient_su2(4, su2_gates=["rx", "y"], entanglement="linear", reps=1)
print(SU2_ansatz.draw())
SU2_ansatz.decompose().draw(output="mpl")
┌──────────┐┌───┐     ┌──────────┐   ┌───┐                     
q_0: ┤ Rx(θ[0]) ├┤ Y ├──■──┤ Rx(θ[4]) ├───┤ Y ├─────────────────────
├──────────┤├───┤┌─┴─┐└──────────┘┌──┴───┴───┐ ┌───┐
q_1: ┤ Rx(θ[1]) ├┤ Y ├┤ X ├─────■──────┤ Rx(θ[5]) ├───┤ Y ├─────────
├──────────┤├───┤└───┘ ┌─┴─┐ └──────────┘┌──┴───┴───┐┌───┐
q_2: ┤ Rx(θ[2]) ├┤ Y ├────────┤ X ├─────────■──────┤ Rx(θ[6]) ├┤ Y ├
├──────────┤├───┤ └───┘ ┌─┴─┐ ├──────────┤├───┤
q_3: ┤ Rx(θ[3]) ├┤ Y ├────────────────────┤ X ├────┤ Rx(θ[7]) ├┤ Y ├
└──────────┘└───┘ └───┘ └──────────┘└───┘

Output of the previous code cell

SU(2) Gate는 su2_gates = [...]에서 지정된 순서와 요소로 시작과 끝에 나타납니다. 얽힘 방식 linear는 CX Gate가 번호가 매겨진 Qubit들을 거쳐 진행되며, 0번과 1번, 그 다음 1번과 2번을 얽히게 하는 식으로 Circuit의 대각선을 따라 내려가는 것을 의미합니다. 예상할 수 있듯이, reps = 2로 설정하면 단순히 얽힘 계층과 마지막 SU(2) 계층이 추가됩니다. reps = n 설정은 n개의 얽힘 계층에 해당하며, 각 얽힘 계층 사이와 양 끝에 SU(2) 계층이 배치됩니다.

SU2_ansatz2 = efficient_su2(
4, su2_gates=["rx", "y", "z"], entanglement="linear", reps=2
)
SU2_ansatz2.decompose().draw(output="mpl")

Output of the previous code cell

그 외에도 여러 얽힘 방식이 있습니다. 주목할 만한 두 가지는 circularfull입니다. Circular 얽힘은 linear 얽힘과 동일하지만, 첫 번째 Qubit과 마지막 Qubit을 얽히게 하는 추가 CX Gate가 있습니다. Full 얽힘 방식은 모든 Qubit 쌍 사이에 CX Gate를 포함합니다. N-Qubit Circuit의 경우, 이는 N(N1)/2N(N-1)/2 개의 CXCX Gate가 되며, 계산 비용이 커질 수 있다는 점에 유의합니다.

SU2_ansatz3 = efficient_su2(
4, su2_gates=["rx", "y", "z"], entanglement="circular", reps=1
)
SU2_ansatz3.decompose().draw(output="mpl")

Output of the previous code cell

SU2_ansatz4 = efficient_su2(4, su2_gates=["rx", "y", "z"], entanglement="full", reps=1)
SU2_ansatz4.decompose().draw(output="mpl")

Output of the previous code cell

.depth(), 또는 경우에 따라 .decompose().depth()를 사용하여 Circuit의 깊이를 모니터링할 수 있습니다.

print(SU2_ansatz4.decompose().depth())
11

efficient_su2의 일반화는 2-local Circuit이며, 이는 그 자체로 n-local Circuit의 특수한 경우입니다. 2-local Circuit도 SU(2) 블록(또는 회전 블록)과 얽힘 블록을 포함합니다. 여기서는 사용할 얽힘 Gate의 종류를 자유롭게 지정할 수 있으며, 예를 들면 CRX Gate가 있습니다. 이 예에서는 모든 Gate가 매개변수를 받지만, 반드시 그럴 필요는 없습니다. 예를 들어 Y 회전 Gate와 CX 얽힘 Gate를 사용할 수도 있습니다.

from qiskit.circuit.library import n_local

rotation_blocks = ["ry"]
entanglement_blocks = ["crx"]
two_ansatz = n_local(
4, rotation_blocks, entanglement_blocks, "linear", insert_barriers=True, reps=2
)
two_ansatz.decompose().draw(output="mpl")

Output of the previous code cell

이름으로 마지막으로 논의할 ansatz는 Pauli-two-design 입니다. 이 Circuit은 RY(pi/4)RY(pi/4) 의 초기 회전을 포함하며, 회전 계층은 단일 Qubit Pauli 회전을 포함하는데, 그 축은 X, Y, Z 중에서 균등하게 무작위로 선택됩니다. 얽힘 계층은 총 깊이가 2인 쌍별 CZ Gate로 구성됩니다. 이 pauli_two_design과 예를 들어 efficient_su2 사이의 얽힘(및 전체 Circuit) 깊이 차이에 유의합니다.

from qiskit.circuit.library import pauli_two_design

PtwoD_ansatz = pauli_two_design(5, reps=1, seed=10599, insert_barriers=True)
PtwoD_ansatz.decompose().draw(output="mpl")

Output of the previous code cell

이러한 미리 만들어진 변분 Circuit은 원하는 수준의 얽힘을 달성하고 Circuit 깊이를 제한하는 측면에서 모두 유용한 휴리스틱입니다. 그러나 이들에게 마법 같은 요소가 있는 것은 아닙니다. 자신만의 변분 Circuit을 자유롭게 만들 수 있습니다. 실제로 시스템의 목표 상태의 얽힘에 대해 무언가 알고 있는 경우에는 이것이 유리할 수 있습니다.

자신만의 ansatz를 만들려면 매개변수 벡터(아래 3-Qubit 예제의 "theta")의 요소에 대한 함수인 Gate의 일부 부분 집합을 갖는 양자 Circuit을 구성하기만 하면 됩니다.

from qiskit import QuantumCircuit
from qiskit.circuit import ParameterVector

n = 3

theta = ParameterVector("θ", length=n)
qc = QuantumCircuit(n)
qc.h(0)
qc.h(2)
for i in range(n - 1):
qc.cx(i, i + 1)
qc.cz(0, n - 1)
qc.barrier()
for i in range(n):
qc.ry(theta[i], i)
qc.barrier()
qc.cz(0, n - 1)
for i in reversed(range(n - 1)):
qc.cx(i, i + 1)
qc.h(0)
qc.h(1)
own_ansatz = qc
print(own_ansatz.depth())
qc.draw("mpl")
9

Output of the previous code cell

일반적으로 최상의 ansatz를 선택하는 것은 하나의 기술입니다. 최상의 ansatz란 가장 적은 최적화 단계로 목표에 도달하도록 도와주는 ansatz입니다. 나쁠 가능성이 있는 ansatz를 식별하는 것이 더 쉽습니다. 예를 들어, Circuit 깊이가 깊을수록 오류가 누적되는 경향이 있습니다. 오류 완화가 이에 도움을 줄 수 있지만, Circuit 깊이를 합리적인 수준에서 가능한 한 낮게 유지하는 것이 좋은 관행입니다. 하지만 필요한 얽힘을 건너뛰지 마세요. 전체 얽힘 방식을 필요로 하는 목표 상태가 있을 수 있습니다. 상당히 명확한 이유로 형편없는 선택일 가능성이 있는 두 가지 예가 아래에 나와 있습니다. 좋은 ansatz를 선택하는 문제는 이후 섹션에서 수렴 테스트 맥락에서 다시 다룰 것입니다.

이 첫 번째 Circuit은 마지막 Qubit이 다른 Qubit들과 전혀 얽혀 있지 않기 때문에 좋지 않은 선택일 가능성이 높습니다. 실제로 마지막 Qubit에는 계산적으로 의미 있는 작용이 전혀 없습니다. 대부분의 경우, 마지막 Qubit은 다른 Qubit들과 얽히게 하거나 계산에서 제거해야 합니다.

n = 4

theta = ParameterVector("θ", length=n)
qc = QuantumCircuit(n)
qc.h(0)
qc.h(2)
for i in range(n - 2):
qc.cx(i, i + 1)
qc.cz(0, n - 2)
qc.barrier()
for i in range(n):
qc.ry(theta[i], i)
qc.barrier()
qc.cz(0, n - 2)
for i in reversed(range(n - 2)):
qc.cx(i, i + 1)
qc.h(0)
qc.h(1)
own_ansatz2 = qc
print(own_ansatz2.depth())
qc.draw("mpl")
9

Output of the previous code cell

이 마지막 Circuit은 Gate 깊이가 매우 크고, 얽힘 계층을 네 번 반복하는 것이 두 번이나 세 번 반복하는 것보다 목표 상태에 실질적으로 더 잘 맞는 결과를 낼 가능성이 낮기 때문에 좋지 않은 선택일 가능성이 높습니다.

su2_ansatz_long = efficient_su2(
4, su2_gates=["rx", "y", "z"], entanglement="linear", reps=4
)
print(su2_ansatz_long.decompose().depth())
su2_ansatz_long.decompose().draw(output="mpl")
24

Output of the previous code cell

이 Circuit들은 많은 Gate에 아직 미지의 변동 가능한 매개변수가 삽입되어야 한다는 의미에서 "완성된" 것이 아닙니다. 이러한 매개변수는 연속적인 추측을 통해 선택되고, 비용 함수(화학 맥락에서는 일반적으로 바닥 상태 에너지)의 기댓값을 낮추도록 매개변수를 업데이트합니다. 1차원 또는 단지 몇 차원에서는 이것이 사소합니다. 하지만 위 Circuit은 20개의 변분 매개변수를 가지므로, 최소 에너지로 목표 상태를 찾는다는 것은 20차원 상태를 탐색한다는 것을 의미합니다(불필요한 Circuit Gate를 포함하지 말아야 하는 또 다른 이유입니다). 여기서 고전 최적화 알고리즘이 등장하며, 이것이 다음 강의의 주제입니다.