자습서: Q#으로 양자 얽힘 살펴보기
이 자습서에서는 큐비트를 조작하고 측정하며 중첩 및 얽힘의 효과를 보여 주는 프로그램을 작성 Q# 합니다. 특정 양자 상태에서 두 개의 큐비트를 준비하고, 큐비트 Q# 에서 작동하여 상태를 변경하는 방법을 알아보고, 중첩 및 얽힘의 효과를 보여 줍니다. 큐비트 상태, 작업 및 측정값을 소개하는 프로그램을 하나씩 빌드 Q# 합니다.
시작하기 전에 이해해야 할 몇 가지 주요 개념은 다음과 같습니다.
- 클래식 비트는 0 또는 1 같은 단일 이진 값을 보유하는 반면, 큐비트 상태는 두 양자 상태 0과 1의 중첩에 있을 수 있습니다. 가능한 각 양자 상태에는 연결된 확률 진폭이 있습니다.
- 큐비트를 측정하는 행위는 특정 확률로 이진 결과를 생성하고 큐비트의 상태를 중첩에서 바꿉니다.
- 서로 독립적으로 설명할 수 없도록 여러 큐비트를 얽을 수 있습니다. 즉, 얽힌 쌍의 한 큐비트에 어떤 일이 발생하든 다른 큐비트에도 발생합니다.
이 자습서에서는 다음 작업을 수행하는 방법을 알아봅니다.
- 큐비트를 원하는 상태로 초기화하는 작업을 만듭니 Q# 다.
- 큐비트를 중첩에 넣습니다.
- 큐비트 쌍을 얽습니다.
- 큐비트를 측정하고 결과를 관찰합니다.
팁
양자 컴퓨팅 과정을 가속화하려면 Azure Quantum 웹 사이트의 고유한 기능인 Azure Quantum을 사용하여 코드를 확인하세요. 여기서는 기본 제공 Q# 샘플 또는 사용자 고유 Q# 의 프로그램을 실행하고, 프롬프트에서 새 Q# 코드를 생성하고, 한 번의 클릭으로 웹용 VS Code에서 코드를 열고 실행하고, Copilot에게 양자 컴퓨팅에 대한 질문을 할 수 있습니다.
필수 조건
Azure Quantum용 Copilot에서 코드 샘플을 실행하려면 다음이 필요합니다.
- Microsoft(MSA) 전자 메일 계정입니다.
Copilot에 대한 자세한 내용은 Azure Quantum 탐색을 참조 하세요.
알려진 상태로 큐비트 초기화
첫 번째 단계는 큐비트를 알려진 상태로 초기화하는 Q# 연산을 정의하는 것입니다. 이 연산은 큐비트를 클래식 상태로 설정하기 위해 호출할 수 있습니다. 즉, 측정 시 100%의 시간을 반환 Zero
하거나 시간의 100%를 반환 One
합니다. 큐비트를 측정하면 값 Q#Result
또는 값만 가질 수 있는 형식Zero
이 반환됩니다One
.
Azure Quantum용 Copilot를 열고 다음 코드를 코드 편집기 창에 복사합니다. 아직 실행
import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
이 코드 예제는 큐비트 상태를 변환하는 두 가지 연산인 M
및 X
를 소개합니다.
SetQubitState
연산:
- 두 개의 매개 변수를 사용합니다. 즉
Result
, 큐비트에 대해 원하는 상태를 나타내는 형식desired
(Zero
또는One
)과 형식Qubit
을 사용합니다. - 큐비트(
M
또는Zero
)의 상태를 측정하고 결과를One
에 지정된 값과 비교하는 측정 연산desired
을 수행합니다. - 측정값이 비교된 값과 일치하지 않는 경우
X
연산을 실행합니다. 이 연산은 측정이Zero
및One
을 반환할 확률이 역전되도록 큐비트의 상태를 플리핑합니다. 이러한 방식으로SetQubitState
는 항상 대상 큐비트를 원하는 상태로 설정합니다.
종 상태를 테스트하는 테스트 작업 작성
이제 SetQubitState
연산의 효과를 보여 주기 위해 이름이 Main
인 다른 연산을 만듭니다. 이 작업은 두 개의 큐비트를 할당하고 첫 SetQubitState
번째 큐비트를 알려진 상태로 설정한 다음 큐비트를 측정하여 결과를 확인합니다.
다음 코드를 작업 아래의 코드 편집기 창에 복사합니다 SetQubitState
.
operation Main() : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
let count = 1000;
let initial = One;
// allocate the qubits
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
// Count the number of 'Ones' returned:
if resultQ1 == One {
numOnesQ1 += 1;
}
if resultQ2 == One {
numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Display the times that |0> is returned, and times that |1> is returned
Message($"Q1 - Zeros: {count - numOnesQ1}");
Message($"Q1 - Ones: {numOnesQ1}");
Message($"Q2 - Zeros: {count - numOnesQ2}");
Message($"Q2 - Ones: {numOnesQ2}");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
코드 count
에서 변수와 initial
변수는 각각 설정 1000
됩니다 One
. 그러면 첫 번째 큐비트를 One
로 초기화하고 각 큐비트를 1,000번 측정합니다.
Main
연산:
- 카운터 및 초기 큐비트 상태에 대한 변수를 설정합니다.
-
use
문을 호출하여 두 큐비트를 초기화합니다. -
count
반복을 반복합니다. 각 루프에 대해-
SetQubitState
를 호출하여 첫 번째 큐비트에 지정된initial
값을 설정합니다. -
SetQubitState
를 다시 호출하여 두 번째 큐비트를Zero
상태로 설정합니다. -
M
연산을 사용하여 각 큐비트를 측정합니다. -
One
을 반환하는 각 큐비트의 측정 수를 저장합니다.
-
- 루프가 완료되면
SetQubitState
를 다시 호출하여 큐비를 알려진 상태(Zero
)로 다시 설정합니다. 그러면 다른 사용자가 큐비트를 알려진 상태에서 할당할 수 있습니다. 다시 설정은 문에use
필요합니다. - 마지막으로, 결과를 반환하기 전에 이 함수를 사용하여
Message
결과를 코필로트 출력 창에 출력합니다.
Azure Quantum에 대한 Copilot에서 코드 실행
중첩 및 얽힘 프로시저로 이동하기 전에 이 시점까지 코드를 테스트하여 큐비트의 초기화 및 측정을 확인할 수 있습니다.
코드를 독립 실행형 프로그램으로 실행하려면 Copilot의 Q# 컴파일러가 프로그램을 시작할 위치를 알고 있어야 합니다. 네임스페이스를 지정하지 않으므로 컴파일러는 기본 진입점을 작업으로 Main
인식합니다. 자세한 내용은 프로젝트 및 암시적 네임스페이스를 참조 하세요.
Q# 이제 이 시점까지의 프로그램은 다음과 같이 표시됩니다.
import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
operation Main() : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
let count = 1000;
let initial = One;
// allocate the qubits
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
// Count the number of 'Ones' returned:
if resultQ1 == One {
numOnesQ1 += 1;
}
if resultQ2 == One {
numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Display the times that |0> is returned, and times that |1> is returned
Message($"Q1 - Zeros: {count - numOnesQ1}");
Message($"Q1 - Ones: {numOnesQ1}");
Message($"Q2 - Zeros: {count - numOnesQ2}");
Message($"Q2 - Ones: {numOnesQ2}");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
전체 코드 샘플을 복사하여 Azure Quantum 코드 창의
Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0
큐비트는 아직 조작되지 않았기 때문에 초기 값을 유지했습니다. 첫 번째 큐비트는 매번 One
을 반환하고 두 번째 큐비트는 Zero
을 반환합니다.
값을 initial
Zero
변경하고 프로그램을 다시 실행하는 경우 첫 번째 큐비트가 매번 반환 Zero
되는지 확인해야 합니다.
Q1 - Zeros: 1000
Q1 - Ones: 0
Q2 - Zeros: 1000
Q2 - Ones: 0
팁
Ctrl-Z>다시 실행하기 전에 코드에 테스트 변경 내용을 적용할 때마다 파일을 저장합니다.
큐비트를 중첩에 넣기
현재 프로그램의 큐비트는 모두 클래식 상태입니다. 즉, 1 또는 0입니다. 프로그램에서 큐비트를 알려진 상태로 초기화하고 조작할 프로세스를 추가하지 않았기 때문에 이를 알 수 있습니다. 큐비트를 얽기 전에 첫 번째 큐비트를 중첩 상태로 전환합니다. 여기서 큐비트의 측정값은 시간의 ~50%와 Zero
시간의 ~50%를 반환 One
합니다. 개념적으로 큐비트는 측정 Zero
확률이 같거나 One
같은 것으로 간주할 수 있습니다.
큐비트를 중첩에 배치하기 위해 Q#에서는 H
또는 Hadamard 연산을 제공합니다.
X
큐비트를 0에서 프로시저로 큐비트 초기화 작업을 회수합니다. 이 작업은 큐비트를 H
동일한 확률 또는 Zero
같음 상태로 대칭 이동합니다. 측정할 때 중첩의 큐비트는 대략 동일한 수의 Zero
및 One
결과를 반환해야 합니다.
초기 값을 Main
다시 설정하여 작업의 줄을 One
삽입하여 작업의 코드를 H
수정합니다.
for test in 1..count {
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
H(q1); // Add the H operation after initialization and before measurement
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
...
이제 프로그램을 실행할 때 중첩에서 첫 번째 큐비트의 결과를 볼 수 있습니다.
Q1 - Zeros: 523 // results vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0
프로그램을 실행할 때마다 첫 번째 큐비트의 결과는 약간 다르지만 50% One
와 50%에 Zero
가까우며 두 번째 큐비트의 결과는 항상 유지됩니다 Zero
.
Q1 - Zeros: 510
Q1 - Ones: 490
Q2 - Zeros: 1000
Q2 - Ones: 0
첫 번째 큐비트를 Zero
로 초기화하면 유사한 결과가 반환됩니다.
Q1 - Zeros: 504
Q1 - Ones: 496
Q2 - Zeros: 1000
Q2 - Ones: 0
참고 항목
Azure Quantum의 Copilot에서 슬라이더를 이동하고 샷 수를 늘리면 중첩 결과가 샷 분포에 따라 약간 달라지는 방식을 확인할 수 있습니다.
두 큐비트 얽기
앞에서 설명한 것처럼 얽힌 큐비트는 서로 독립적으로 설명할 수 없도록 연결됩니다. 즉, 하나의 큐비트에 어떤 연산이 일어나든 얽힌 큐비트에도 발생합니다. 이렇게 하면 다른 큐비트의 상태를 측정하여 측정하지 않고 한 큐비트의 결과 상태를 알 수 있습니다. 이 예제에서는 두 큐비트를 사용하지만 셋 이상의 큐비트를 얽을 수도 있습니다.
얽힘을 사용하도록 설정하기 위해 Q#에서는 CNOT
Controled-NOT을 나타내는 연산을 제공합니다. 두 큐비트에 대해 이 연산을 실행하면 그 결과로 첫 번째 큐비트가 One
인 경우 두 번째 큐비트가 대칭 이동됩니다.
프로그램에서 CNOT
연산 바로 다음에 H
연산을 추가합니다. 전체 프로그램은 다음과 같습니다.
import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
operation Main() : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
let count = 1000;
let initial = Zero;
// allocate the qubits
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
H(q1);
CNOT(q1, q2); // Add the CNOT operation after the H operation
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
// Count the number of 'Ones' returned:
if resultQ1 == One {
numOnesQ1 += 1;
}
if resultQ2 == One {
numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Display the times that |0> is returned, and times that |1> is returned
Message($"Q1 - Zeros: {count - numOnesQ1}");
Message($"Q1 - Ones: {numOnesQ1}");
Message($"Q2 - Zeros: {count - numOnesQ2}");
Message($"Q2 - Ones: {numOnesQ2}");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
이제 프로그램을 실행할 때 다음과 같은 내용이 표시됩니다.
Q1 - Zeros: 502 // results will vary
Q1 - Ones: 498
Q2 - Zeros: 502
Q2 - Ones: 498
첫 번째 큐비트에 대한 통계는 변경되지 않았지만(측정 후 최대 50/50의 Zero
One
확률은 여전히 있음) 두 번째 큐비트의 측정 결과는 프로그램을 실행하는 횟수에 관계없이 항상 첫 번째 큐비트의 측정값과 동일합니다.
CNOT
연산은 두 큐비트를 얽어서 두 큐비트 중 한 큐비트에서 발생하는 모든 것이 다른 큐비트에서 발생하도록 했습니다.
필수 조건
로컬 개발 환경에서 코드 샘플을 개발하고 실행하려면 다음을 수행합니다.
- 최신 버전의 Visual Studio Code 또는 웹에서 VS Code를 엽니다.
- 최신 버전의 Azure Quantum 개발 키트 확장. 설치 세부 정보는 QDK 확장설정을 참조하세요.
새 Q# 파일 만들기
- Visual Studio Code를 열고 파일>새 텍스트 파일을 선택하여 새 파일을 만듭니다.
- 파일을
CreateBellStates.qs
로 저장합니다. 이 파일에는 프로그램에 대한 코드가 Q# 포함됩니다.
알려진 상태로 큐비트 초기화
첫 번째 단계는 큐비트를 알려진 상태로 초기화하는 Q# 연산을 정의하는 것입니다. 이 작업을 호출하여 큐비트를 클래식 상태로 설정할 수 있습니다. 즉, 100%의 시간을 반환 Zero
하거나 시간의 100%를 반환 One
합니다.
Zero
및 One
은 큐비트 측정에서 가능한 두 가지 결과를 나타내는 Q# 값입니다.
다음 코드를 열고 CreateBellStates.qs
복사합니다.
import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
이 코드 예제는 큐비트 상태를 변환하는 두 가지 연산인 M
및 X
를 소개합니다.
SetQubitState
연산:
- 두 개의 매개 변수를 사용합니다. 즉
Result
, 큐비트에 대해 원하는 상태를 나타내는 형식desired
(Zero
또는One
)과 형식Qubit
을 사용합니다. - 큐비트(
M
또는Zero
)의 상태를 측정하고 결과를One
에 지정된 값과 비교하는 측정 연산desired
을 수행합니다. - 측정값이 비교된 값과 일치하지 않는 경우
X
연산을 실행합니다. 이 연산은 측정이Zero
및One
을 반환할 확률이 역전되도록 큐비트의 상태를 플리핑합니다. 이러한 방식으로SetQubitState
는 항상 대상 큐비트를 원하는 상태로 설정합니다.
종 상태를 테스트하는 테스트 작업 작성
이제 SetQubitState
연산의 효과를 보여 주기 위해 이름이 Main
인 다른 연산을 만듭니다. 이 작업은 두 개의 큐비트를 할당하고, SetQubitState
첫 번째 큐비트를 알려진 상태로 설정한 다음, 큐비트를 측정하여 결과를 확인합니다.
CreateBellStates.qs
파일에서 SetQubitState
연산 이후에 다음 연산을 추가합니다.
operation Main() : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
let count = 1000;
let initial = One;
// allocate the qubits
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
// Count the number of 'Ones' returned:
if resultQ1 == One {
numOnesQ1 += 1;
}
if resultQ2 == One {
numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Display the times that |0> is returned, and times that |1> is returned
Message($"Q1 - Zeros: {count - numOnesQ1}");
Message($"Q1 - Ones: {numOnesQ1}");
Message($"Q2 - Zeros: {count - numOnesQ2}");
Message($"Q2 - Ones: {numOnesQ2}");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
코드 count
에서 변수와 initial
변수는 각각 설정 1000
됩니다 One
. 이 단계에서는 첫 번째 큐비트를 초기화하고 각 큐비 One
트를 1000번 측정합니다.
Main
연산:
- 두 매개 변수를 사용합니다. 하나는 측정을 실행할 횟수인
count
이고 다른 하나는 큐비트를 초기화할 필요한 상태인initial
입니다. -
use
문을 호출하여 두 큐비트를 초기화합니다. -
count
반복을 반복합니다. 각 루프에 대해-
SetQubitState
를 호출하여 첫 번째 큐비트에 지정된initial
값을 설정합니다. -
SetQubitState
를 다시 호출하여 두 번째 큐비트를Zero
상태로 설정합니다. -
M
연산을 사용하여 각 큐비트를 측정합니다. -
One
을 반환하는 각 큐비트의 측정 수를 저장합니다.
-
- 루프가 완료되면
SetQubitState
를 다시 호출하여 큐비를 알려진 상태(Zero
)로 다시 설정합니다. 그러면 다른 사용자가 큐비트를 알려진 상태에서 할당할 수 있습니다. 문에는 큐비트를 다시 설정해야use
합니다. - 마지막으로, 결과를 반환하기 전에
Message
함수를 사용하여 콘솔에 메시지를 출력합니다.
코드 실행
중첩 및 얽힘 프로시저로 이동하기 전에 이 지점까지 코드를 테스트하여 큐비트의 초기화 및 측정을 확인합니다.
코드를 독립 실행형 프로그램으로 실행하려면 컴파일러가 Q# 프로그램을 시작할 위치를 알고 있어야 합니다. 네임스페이스를 지정하지 않으므로 컴파일러는 기본 진입점을 작업으로 Main
인식합니다. 자세한 내용은 프로젝트 및 암시적 네임스페이스를 참조 하세요.
CreateBellStates.qs
이제 이 시점까지의 파일은 다음과 같습니다.import Microsoft.Quantum.Intrinsic.*; import Microsoft.Quantum.Canon.*; operation SetQubitState(desired : Result, target : Qubit) : Unit { if desired != M(target) { X(target); } } operation Main() : (Int, Int, Int, Int) { mutable numOnesQ1 = 0; mutable numOnesQ2 = 0; let count = 1000; let initial = One; // allocate the qubits use (q1, q2) = (Qubit(), Qubit()); for test in 1..count { SetQubitState(initial, q1); SetQubitState(Zero, q2); // measure each qubit let resultQ1 = M(q1); let resultQ2 = M(q2); // Count the number of 'Ones' returned: if resultQ1 == One { numOnesQ1 += 1; } if resultQ2 == One { numOnesQ2 += 1; } } // reset the qubits SetQubitState(Zero, q1); SetQubitState(Zero, q2); // Display the times that |0> is returned, and times that |1> is returned Message($"Q1 - Zeros: {count - numOnesQ1}"); Message($"Q1 - Ones: {numOnesQ1}"); Message($"Q2 - Zeros: {count - numOnesQ2}"); Message($"Q2 - Ones: {numOnesQ2}"); return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 ); }
프로그램을 실행하기 전에 대상 프로필이 무제한으로 설정되어 있는지 확인합니다. 보기 - 명령 팔레트를 선택하고>
참고 항목
대상 프로필이 무제한으로 설정되지 않은 경우 프로그램을 실행할 때 오류가 발생합니다.
프로그램을 실행하려면 오른쪽 위에 있는 재생 아이콘 드롭다운에서 파일 실행을 선택하고, 작업 앞의 명령 목록에서 실행을Q#하거나, Ctrl+F5를 누릅니
Main
다. 프로그램은 기본 시뮬레이터에서 작업을 실행Main
합니다.출력이 디버그 콘솔에 표시됩니다.
Q1 - Zeros: 0 Q1 - Ones: 1000 Q2 - Zeros: 1000 Q2 - Ones: 0
큐비트는 아직 조작되지 않았기 때문에 초기 값을 유지했습니다. 첫 번째 큐비트는 매번
One
을 반환하고 두 번째 큐비트는Zero
을 반환합니다.값을
initial
Zero
변경하고 프로그램을 다시 실행하는 경우 첫 번째 큐비트가 매번 반환Zero
되는지 확인해야 합니다.Q1 - Zeros: 1000 Q1 - Ones: 0 Q2 - Zeros: 1000 Q2 - Ones: 0
팁
Ctrl-Z>다시 실행하기 전에 코드에 테스트 변경 내용을 적용할 때마다 파일을 저장합니다.
큐비트를 중첩에 넣기
현재 프로그램의 큐비트는 모두 클래식 상태입니다. 즉, 1 또는 0입니다. 프로그램에서 큐비트를 알려진 상태로 초기화하고 조작할 프로세스를 추가하지 않았기 때문에 이를 알 수 있습니다. 큐비트를 얽기 전에 첫 번째 큐비트를 중첩 상태로 전환합니다. 여기서 큐비트의 측정값은 시간의 50%와 Zero
시간의 50%를 반환 One
합니다. 개념적으로 큐비트는 Zero
와 One
의 중간으로 생각할 수 있습니다.
큐비트를 중첩에 배치하기 위해 Q#에서는 H
또는 Hadamard 연산을 제공합니다.
X
큐비트를 이전에 알려진 상태회수합니다. 이 연산은 큐비트를 Zero
같은 확률 One
또는 H
같은 상태로 대칭 이동합니다. 측정할 때 중첩의 큐비트는 대략 동일한 수의 Zero
및 One
결과를 반환해야 합니다.
Main
연산을 포함하도록H
연산의 코드를 수정합니다.for test in 1..count { use (q1, q2) = (Qubit(), Qubit()); for test in 1..count { SetQubitState(initial, q1); SetQubitState(Zero, q2); H(q1); // Add the H operation after initialization and before measurement // measure each qubit let resultQ1 = M(q1); let resultQ2 = M(q2); ...
이제 프로그램을 실행할 때 중첩에서 첫 번째 큐비트의 결과를 볼 수 있습니다.
Q1 - Zeros: 523 // results will vary Q1 - Ones: 477 Q2 - Zeros: 1000 Q2 - Ones: 0
프로그램을 실행할 때마다 첫 번째 큐비트의 결과는 약간 다르지만 50%
One
와 50%에Zero
가까우며 두 번째 큐비트의 결과는 항상 유지됩니다Zero
.Q1 - Zeros: 510 Q1 - Ones: 490 Q2 - Zeros: 1000 Q2 - Ones: 0
첫 번째 큐비트를
Zero
로 초기화하면 유사한 결과가 반환됩니다.Q1 - Zeros: 504 Q1 - Ones: 496 Q2 - Zeros: 1000 Q2 - Ones: 0
두 큐비트 얽기
앞에서 설명한 것처럼 얽힌 큐비트는 서로 독립적으로 설명할 수 없도록 연결됩니다. 즉, 하나의 큐비트에 어떤 연산이 일어나든 얽힌 큐비트에도 발생합니다. 이렇게 하면 다른 큐비트의 상태를 측정하여 측정하지 않고 한 큐비트의 결과 상태를 알 수 있습니다. 이 예제에서는 두 큐비트를 사용하지만 셋 이상의 큐비트를 얽을 수도 있습니다.
얽힘을 사용하도록 설정하기 위해 Q#에서는 CNOT
Controled-NOT을 나타내는 연산을 제공합니다. 두 큐비트에 대해 이 연산을 실행하면 그 결과로 첫 번째 큐비트가 One
인 경우 두 번째 큐비트가 대칭 이동됩니다.
프로그램에서
CNOT
연산 바로 다음에H
연산을 추가합니다. 전체 프로그램은 다음과 같습니다.import Microsoft.Quantum.Intrinsic.*; import Microsoft.Quantum.Canon.*; operation SetQubitState(desired : Result, target : Qubit) : Unit { if desired != M(target) { X(target); } } operation Main() : (Int, Int, Int, Int) { mutable numOnesQ1 = 0; mutable numOnesQ2 = 0; let count = 1000; let initial = Zero; // allocate the qubits use (q1, q2) = (Qubit(), Qubit()); for test in 1..count { SetQubitState(initial, q1); SetQubitState(Zero, q2); H(q1); CNOT(q1, q2); // Add the CNOT operation after the H operation // measure each qubit let resultQ1 = M(q1); let resultQ2 = M(q2); // Count the number of 'Ones' returned: if resultQ1 == One { numOnesQ1 += 1; } if resultQ2 == One { numOnesQ2 += 1; } } // reset the qubits SetQubitState(Zero, q1); SetQubitState(Zero, q2); // Display the times that |0> is returned, and times that |1> is returned Message($"Q1 - Zeros: {count - numOnesQ1}"); Message($"Q1 - Ones: {numOnesQ1}"); Message($"Q2 - Zeros: {count - numOnesQ2}"); Message($"Q2 - Ones: {numOnesQ2}"); return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 ); }
Q1 - Zeros: 502 Q1 - Ones: 498 // results will vary Q2 - Zeros: 502 Q2 - Ones: 498 Result: "(502, 498, 502, 498)"
첫 번째 큐비트에 대한 통계는 변경되지 않았지만(측정 후 Zero
또는 One
의 확률 50/50) 두 번째 큐비트의 측정 결과는 항상 첫 번째 큐비트의 측정과 동일합니다. 이 CNOT
작업은 두 큐비트를 얽혀 그 중 하나에 어떤 일이 일어나든 다른 큐비트가 발생하도록 했습니다.
빈도 히스토그램 그리기
양자 프로그램을 여러 번 실행하여 얻은 결과의 분포를 시각화해 보겠습니다. 빈도 히스토그램은 이러한 결과의 확률 분포를 시각화하는 데 도움이 됩니다.
보기 - 명령 팔레트>하거나 Ctrl+Shift+P를 누르고 : 파일을 표시Q#"을 입력합니다. 앞의 명령 목록에서 히스토그램을 선택할 수도 있습니다
Main
. 히스토그램 창을 열려 Q# 면 이 옵션을 선택합니다.프로그램을 실행하는 여러 샷 (예: 100개의 샷)을 입력하고 Enter 키를 누릅니 다. 히스토그램 창에 히스토그램이 Q# 표시됩니다.
히스토그램의 각 막대는 가능한 결과에 해당하며, 높이가 결과가 관찰되는 횟수를 나타냅니다. 이 경우 50개의 고유한 결과가 있습니다. 각 결과에 대해 첫 번째 큐비트와 두 번째 큐비트의 측정 결과는 항상 동일합니다.
팁
마우스 스크롤 휠 또는 트랙 패드 제스처를 사용하여 히스토그램을 확대/축소할 수 있습니다. 확대하면 스크롤하는 동안 Alt 키를 눌러 차트를 이동하면 됩니다.
막대를 선택하여 해당 결과의 백분율을 표시합니다.
왼쪽 위 설정 아이콘 을 선택하여 옵션을 표시합니다. 상위 10개 결과, 상위 25개 결과 또는 모든 결과를 표시할 수 있습니다. 결과를 높음에서 낮음 또는 낮음에서 높음으로 정렬할 수도 있습니다.
관련 콘텐츠
다른 Q# 자습서 살펴보기:
- Grover의 검색 알고리즘 은 Grover의 검색 알고리즘을 Q# 사용하는 프로그램을 작성하는 방법을 보여줍니다.
- Quantum Fourier Transform 은 특정 큐비트를 Q# 직접 해결하는 프로그램을 작성하는 방법을 살펴봅니다.
- Quantum Katas는 양자 컴퓨팅 및 프로그래밍 요소를 동시에 교육하기 위한 자가 진행 자습서 및 Q# 프로그래밍 연습입니다.