양자 컴퓨터 시뮬레이터
JavaScript로 작은 양자 회로를 작성하고 브라우저에서 바로 시뮬레이션하여 회로도, 확률과 상태 벡터를 확인할 수 있습니다. 덧셈 같은 계산을 고수준으로 작성한 뒤 실제 가역 양자 회로로 자동 변환되는 과정도 살펴볼 수 있습니다.
잡음 모형
실제 양자 컴퓨터는 완벽하게 계산하지 못합니다. 큐비트는 매우 민감하여 열, 전자기장, 이웃 큐비트 등 환경과의 원치 않는 상호작용으로 정보 일부를 잃습니다(결잃음). 게이트 연산에도 오차가 있고 마지막 판독에도 오류가 생깁니다. 이 시뮬레이터는 처음에는 이상적으로 계산하지만 여기에서 대표적인 오류 모형을 활성화해 결과에 미치는 영향을 직접 관찰할 수 있습니다.
quantum.add, quantum.subtract, quantum.multiply, quantum.divide, quantum.random으로 계산을 작성합니다. Ctrl+Enter로 시뮬레이션을 시작합니다. 자세한 내용은 ‘문서’ 버튼을 여세요.
이 코드는 위의 프로그램 코드에서 자동으로 생성되어 직접 시뮬레이션되었습니다. 여기서 직접 편집하고 다시 실행할 수 있습니다.
생성된 회로를 직접 편집했으므로 도표의 레지스터 구분을 숨깁니다. 위의 프로그램 코드를 다시 실행하면 변경 내용이 덮어쓰입니다.
최대 4,000자. 사용 가능한 QuantumCircuit 메서드: x, y, z, h, s, sdg, t, tdg, rx, ry, rz, cnot, cz, ccnot(다른 이름: toffoli), swap, measureAll, run. Ctrl+Enter로 시뮬레이션을 시작합니다.
회로도
단계 표시에서는 선택한 게이트 직후의 확률과 상태 벡터를 정확히 보여 줍니다. 아래 shot 결과는 항상 전체 회로에 적용됩니다.
OpenQASM 2.0
OpenQASM 2.0은 양자 회로에서 널리 쓰이는 교환 형식이며 Qiskit 등에서 불러올 수 있습니다. 비트 순서에 주의하세요. 이 시뮬레이터에서는 q0이 최상위(왼쪽)이지만 Qiskit에서는 q[0]이 최하위이므로 측정 비트열이 좌우 반전되어 표시됩니다.
확률
각 비트열을 측정할 확률을 상태 벡터에서 정확히 계산합니다. 읽는 방향: q0은 가장 왼쪽의 최상위 비트입니다.
블로흐 구
각 큐비트의 상태를 블로흐 구 안의 화살표로 표시합니다. 북극 = |0⟩, 남극 = |1⟩, 적도 = 같은 가중치의 중첩입니다. 화살표가 구의 반지름보다 눈에 띄게 짧으면 그 큐비트는 단독 순수 상태가 아니며 다른 큐비트와 얽혀 있습니다. 잡음도 화살표를 짧게 만듭니다. 잡음 모형이 활성화되면 결맞음이 사라져 화살표가 안쪽으로 줄어듭니다. 여기서 잡음이 포함된 구는 잡음 궤적을 평균한 근사치입니다. 위의 단계 표시에서는 게이트마다 화살표가 움직입니다(잡음이 없을 때만).
shot 결과
시뮬레이션 측정에서 각 비트열이 실제로 나온 횟수입니다. 결과가 여러 개라면 횟수는 정확한 확률 주변에서 무작위로 달라집니다.
상태 벡터
확률의 바탕이 되는 복소 진폭입니다. 진폭 절댓값의 제곱(실수부² + 허수부²)이 해당 상태의 확률입니다.
| 상태 | 실수부 | 허수부 |
|---|
기초: 작동 원리
프로그램에서 물리적 큐비트까지
실제 양자 컴퓨터는 칩만으로 이루어지지 않습니다. 고전 제어 회로가 회로를 정밀한 펄스로 변환합니다. 이온 트랩 방식 등에서는 냉각, 재펌핑, 큐비트 조작과 판독용 레이저를 광학계로 다듬어 차폐된 진공 용기로 보냅니다. 그곳에서 큐비트 상태를 바꾸고 측정한 뒤 결과를 고전 컴퓨터로 돌려보냅니다.
큐비트와 기저 상태
고전 비트는 0 또는 1입니다. 큐비트는 두 기저 상태 |0⟩ 와 |1⟩의 중첩이 될 수도 있습니다. 여러 큐비트의 기저 상태는 비트열로 나타내며, 예를 들어 2큐비트의 |10⟩ 에서 이 시뮬레이터의 q0 은 항상 가장 왼쪽의 최상위 비트입니다.
중첩
중첩 상태의 큐비트는 여러 기저 상태의 성분을 동시에 가집니다. 성분은 복소 진폭으로 나타내며 진폭 절댓값의 제곱이 측정할 때 해당 상태가 나올 확률입니다.
블로흐 구
1큐비트 상태는 구 안의 화살표로 나타낼 수 있습니다. 북극은 |0⟩, 남극은 |1⟩, 적도 위는 같은 가중치의 중첩이며 위상이 적도 위의 방향을 정합니다. 회전 게이트 rx, ry, rz 는 각 축을 중심으로 화살표를 돌리고 S나 T 같은 위상 게이트는 Z축을 중심으로 돌립니다. 큐비트가 얽히면 화살표가 중심으로 줄어 단독 순수 상태가 없음을 시각화합니다.
측정과 shots
measureAll() 은 모든 큐비트를 한 번에 측정하고 회로를 끝냅니다. 한 번 측정하면 무작위 결과 하나만 얻으므로 run({ shots })로 개념상 shots회 측정하고 확률분포를 히스토그램으로 나타냅니다. 정확한 확률은 shot의 무작위성과 별개로 상태 벡터에서 직접 계산합니다.
하다마드 게이트
하다마드 게이트 h(q) 는 확정 상태|0⟩ 또는 |1⟩의 큐비트를 |0⟩ 과 |1⟩ 이 같은 가중치를 갖는 중첩으로 바꿉니다. 측정하면 각각 약 50%가 됩니다.
위상 게이트: S와 T
위상 게이트 s(q) 와 t(q) 는 단독 큐비트의 측정 확률을 바꾸지 않고 |1⟩ 진폭의 위상만 S는 90도, T는 45도 회전합니다. 중첩과 조합하면 효과가 나타나며 두 하다마드 사이에서는 위상에 따라 진폭이 보강되거나 상쇄됩니다. 대거 버전인 sdg(q) 와 tdg(q) 는 반대 방향으로 회전해 S와 T를 취소합니다. T를 두 번 적용하면 S, S를 두 번 적용하면 Z가 됩니다.
CNOT과 조건부 양자 얽힘
CNOT 게이트 cnot(control, target) 는 제어 큐비트가 |1⟩일 때만 표적을 뒤집습니다. 제어 큐비트가 미리 중첩 상태라면 벨 상태 같은 양자 얽힘을 만들 수 있습니다. 제어 큐비트가 확정된 기저 상태라면 얽힘을 만들지 않고 조건부 비트 반전만 수행합니다. CNOT이 항상 얽힘을 만드는 것은 아닙니다.
CZ: CNOT의 대칭형 짝
CZ 게이트 cz(a, b) 는 두 큐비트가 모두 |1⟩일 때만 진폭의 부호를 뒤집습니다. CNOT과 달리 제어와 표적의 구분이 없고 두 큐비트에 똑같이 작용하므로 도표에서는 연결된 두 점으로 그립니다. 표적 앞뒤에 하다마드를 놓으면 CZ를 CNOT으로 바꿀 수 있습니다. CZ는 그로버 탐색을 비롯한 여러 알고리즘의 핵심 구성 요소입니다.
GHZ 상태: 3큐비트 얽힘
그린버거, 혼, 차일링거의 이름을 딴 GHZ 상태는 벨 상태를 3큐비트로 확장합니다. 하다마드 하나와 CNOT 두 개로 모두 얽히게 하면 측정 결과는 |000⟩ 또는 |111⟩ 만 나오며 혼합된 비트열은 나타나지 않습니다. 각 큐비트는 단독 상태가 없고 정보는 공유된 상관관계에만 존재합니다.
도이치 알고리즘: 가장 작은 양자적 우위
도이치 알고리즘은 알 수 없는 오라클을 한 번만 평가해 고전 컴퓨터라면 두 번 평가해야 하는 질문, 즉 함수가 상수 함수인지 균형 함수인지 답합니다. 입력을 중첩 상태로 오라클에 통과시키면 간섭을 통해 답이 입력 큐비트에 명확히 부호화됩니다. 이러한 위상 되먹임 원리는 거의 모든 양자 알고리즘의 핵심입니다.
그로버 탐색: 진폭 증폭
그로버 탐색은 고전적인 방법보다 적은 질의로 정렬되지 않은 집합에서 표시된 원소를 찾습니다. 오라클이 위상 반전으로 대상 상태에 표시하며 여기서는 CZ를 사용합니다. 그런 다음 확산 연산자가 다른 진폭을 줄이는 대신 대상 진폭을 증폭합니다. 2큐비트라면 한 번 반복해 대상을 100% 확률로 측정할 수 있습니다.
가역 덧셈: quantum.add()에서 회로로
위의 프로그램 코드는 quantum.add({ a, b }) 를 고전 덧셈을 완전히 가역적으로 재현하는 X, CNOT, CCNOT(토폴리) 게이트 회로로 바꿉니다. 정보를 버리지 않으므로 각 게이트를 정확히 취소할 수 있습니다. CCNOTccnot(c1, c2, target)은 두 제어 큐비트가 모두 |1⟩ 일 때만 표적을 뒤집으며 올림이 있는 전가산기를 포함한 모든 고전 회로를 가역적으로 구성할 수 있습니다. 입력 A와 B는 X 게이트로 확정된 기저 상태로 초기화됩니다. 전체 회로가 중첩이 아닌 확정 상태만 지나므로 마지막 측정에서는 고전적으로 올바른 합 하나만 100% 확률로 나옵니다. 따라서 양자 시뮬레이션이어도 quantum.add() 은 확률이 100% 미만인 여러 상태가 아니라 결정론적 결과를 반환합니다.
뺄셈: 덧셈을 역방향으로 실행
양자 회로의 각 게이트는 정확히 역변환할 수 있으므로 덧셈 회로 전체를 역방향으로 실행하면 뺄셈이 됩니다. quantum.subtract({ a, b }) 는 덧셈기의 게이트를 역순으로 사용해 a − b를 계산합니다. 이는 계산 단계가 정보를 없애지 않고 모두 취소할 수 있다는 가역 계산의 기본 원리입니다. 이 버전에서는 음수 결과를 피하기 위해 a ≥ b여야 합니다.
곱셈: quantum.multiply()
곱셈도 덧셈과 같은 가역 구성 요소로 만듭니다. 세로셈처럼 인수 b에서 1인 비트에 따라 인수 a의 위치를 옮겨 여러 번 더합니다. 각 부분 덧셈은 같은 가역 리플 올림 덧셈기를 사용하며 올림이 다음 곱 비트로 전달됩니다. 결과 레지스터는 곱에 맞춰 커지므로 여기서는 인수를 3비트(0~7)로 제한해 인수, 곱과 올림 큐비트를 10큐비트 안에 맞춥니다.
나눗셈: quantum.divide()
나눗셈도 가역 구성 요소만 사용합니다: quantum.divide({ a, b }) 는 나머지 레지스터에서 제수의 위치를 옮겨 가며 가역적으로 빼는 긴 나눗셈을 수행하고 결과로 몫 과 나머지를 반환합니다(a = quotient · b + remainder). 피제수, 제수, 몫 및 빌림 큐비트를 10큐비트 안에 맞추려면 bits(a) + bits(b) + bits(a÷b) + 1 ≤ 10 가 필요하며 0으로 나누는 일을 피하려면 제수 b 는 1 이상이어야 합니다. 입력이 예산 안에 들어오지 않으면 계산하지 않고 편집기에 알립니다.
참 난수: quantum.random()
고전 컴퓨터의 난수는 결정론적 알고리즘으로 만든 의사 난수입니다. 양자 컴퓨터에서는 quantum.random({ bits }) 가 각 비트를 하다마드로 50대 50 중첩 상태로 만들고 측정할 때 근본적으로 예측할 수 없는 값을 얻습니다. 실제 양자 하드웨어에서는 물리적인 참 난수지만 이 시뮬레이터는 브라우저의 의사 난수로 모방합니다.
시뮬레이터와 실제 양자 하드웨어
이 시뮬레이터는 브라우저의 고전적인 부동소수점 연산으로 상태를 정확히 계산합니다. 최대 10큐비트의 매우 작은 회로만 다루기 때문에 가능합니다. 실제 양자 컴퓨터는 물리적 큐비트를 사용하며 결잃음과 잡음으로 인한 오류가 있습니다. 고전적으로 실용적인 시간 안에 시뮬레이션할 수 없을 만큼 큰 회로에서야 이점이 나타납니다. 이 도구는 학습용이며 실제 양자 프로세서가 아닙니다.