양자 코드를 디버그하고 테스트하는 방법
클래식 프로그래밍과 마찬가지로 양자 프로그램이 의도한 대로 작동하는지 확인하고 잘못된 동작을 진단할 수 있어야 합니다. 이 문서에서는 양자 프로그램을 테스트하고 디버깅하기 위해 Azure Quantum Development Kit 에서 제공하는 도구에 대해 설명합니다.
프로그램 디버그 Q#
Azure Quantum Development Kit (QDK) Visual Studio Code 확장에는 프로그램에 대한 Q# 디버거가 포함되어 있습니다. 중단점을 설정하고, 코드를 단계별로 실행하고, 각 함수 또는 작업으로 이동하고, 지역 변수뿐만 아니라 큐비트의 양자 상태도 추적할 수 있습니다.
참고 항목
VS Code 디버거는 (.qs) 파일에서 Q# 만 작동하며 Jupyter Notebook의 셀에서는 작동하지 Q# 않습니다. Jupyter Notebook 셀을 테스트하려면 코드 테스트를 참조하세요.
다음 예제에서는 디버거의 기본 기능을 보여 줍니다. VS Code 디버거 사용에 대한 자세한 내용은 디버깅을 참조 하세요.
VS Code에서 다음 코드를 사용하여 새 .qs 파일을 만들고 저장합니다.
import Microsoft.Quantum.Arrays.*;
import Microsoft.Quantum.Convert.*;
operation Main() : Result {
use qubit = Qubit();
H(qubit);
let result = M(qubit);
Reset(qubit);
return result;
}
- 줄 번호의 왼쪽을 클릭하여 줄
H(qubit)
에 중단점을 설정합니다. - 디버거 아이콘을 선택하여 디버거 창을 열고 실행 및 디버그를 선택합니다. 디버거 컨트롤은 화면 맨 위에 표시됩니다.
- F5 키를 선택하여 디버깅을 시작하고 중단점으로 계속 진행합니다. 디버거 변수 창에서 Quantum 상태 범주를 확장합니다. 큐비트가 |0> 상태에서 초기화된 것을 볼 수 있습니다.
- 작업 및 작업의 소스 코드
H
가H
표시되는 (F11) 단계별로 실행합니다. 작업을 단계별로 진행하면서 큐비트가 중첩으로 전환됨에 따라H
양자 값이 변경됩니다. - 연산을
M
단계별로 실행하면 측정 결과로 양자 값이 |0> 또는 |1> 로 확인되고 클래식 변수result
의 값이 표시됩니다. - 작업을 단계별로
Reset
실행하면 큐비트가 |0>으로 다시 설정됩니다.
코드 테스트
Jupyter Notebook의 셀에는 VS Code Q# 디버거를 사용할 수 Q# 없지만 Azure QDK는 코드 문제를 해결하는 데 도움이 되는 몇 가지 식과 함수를 제공합니다.
식 실패
식은 fail
프로그램을 중지하는 치명적인 오류에 해당하는 계산을 완전히 종료합니다.
매개 변수 값의 유효성을 검사하는 간단한 예제를 살펴보겠습니다.
# import qsharp package to access the %%qsharp magic command
import qsharp
// use the %%qsharp magic command to change the cell type from Python to Q#
%%qsharp
function PositivityFact(value : Int) : Unit {
if value <= 0 {
fail $"{value} isn't a positive number.";
}
}
PositivityFact(0);
Error: program failed: 0 isn't a positive number.
Call stack:
at PositivityFact in line_2
Qsc.Eval.UserFail
× runtime error
╰─▶ program failed: 0 isn't a positive number.
╭─[line_2:5:1]
5 │
6 │ fail $"{value} isn't a positive number.";
· ────────────────────┬───────────────────
· ╰── explicit fail
7 │ }
╰────
여기서 식은 fail
프로그램이 잘못된 데이터로 계속 실행되지 않도록 합니다.
Fact() 함수
네임스페이스의 함수를 사용하여 이전 예제와 동일한 동작을 Fact()
구현할 Microsoft.Quantum.Diagnostics
수 있습니다. 함수는 Fact()
지정된 클래식 조건을 평가하고 false이면 예외를 throw합니다.
import qsharp
%%qsharp
function PositivityFact(value : Int) : Unit {
Fact(value > 0, "Expected a positive number.");
}
PositivityFact(4);
Error: program failed: Expected a positive number.
Call stack:
at Microsoft.Quantum.Diagnostics.Fact in diagnostics.qs
at PositivityFact in line_4
Qsc.Eval.UserFail
× runtime error
╰─▶ program failed: Expected a positive number.
╭─[diagnostics.qs:29:1]
29 │ if (not actual) {
30 │ fail message;
· ──────┬─────
· ╰── explicit fail
31 │ }
╰────
DumpMachine() 함수
DumpMachine()
Q# 는 컴퓨터의 target 현재 상태에 대한 정보를 콘솔에 덤프하고 프로그램을 계속 실행할 수 있는 함수입니다.
참고 항목
Azure Quantum Development Kit릴리스에서 이 함수는 DumpMachine()
이제 출력에 big-endian 순서를 사용합니다.
import qsharp
%%qsharp
import Microsoft.Quantum.Diagnostics.*;
operation MultiQubitDumpMachineDemo() : Unit {
use qubits = Qubit[2];
X(qubits[1]);
H(qubits[1]);
DumpMachine();
R1Frac(1, 2, qubits[0]);
R1Frac(1, 3, qubits[1]);
DumpMachine();
ResetAll(qubits);
}
MultiQubitDumpMachineDemo();
Basis State
(|𝜓₁…𝜓ₙ⟩) Amplitude Measurement Probability Phase
|00⟩ 0.7071+0.0000𝑖 50.0000% ↑ 0.0000
|01⟩ −0.7071+0.0000𝑖 50.0000% ↓ -3.1416
Basis State
(|𝜓₁…𝜓ₙ⟩) Amplitude Measurement Probability Phase
|00⟩ 0.7071+0.0000𝑖 50.0000% ↑ 0.0000
|01⟩ −0.6533−0.2706𝑖 50.0000% ↙ -2.7489
dump_machine() 함수
dump_machine
는 현재 할당된 큐비트 수와 구문 분석할 수 있는 스파스 상태 진폭의 Python 사전을 반환하는 Python 함수입니다. Jupyter Notebook에서 이러한 함수 중 하나를 사용하면 디버거처럼 작업을 단계별로 실행할 수 있습니다. 이전 예제 프로그램 사용:
import qsharp
%%qsharp
use qubits = Qubit[2];
X(qubits[0]);
H(qubits[1]);
dump = qsharp.dump_machine()
dump
Basis State
(|𝜓₁…𝜓ₙ⟩) Amplitude Measurement Probability Phase
|10⟩ 0.7071+0.0000𝑖 50.0000% ↑ 0.0000
|11⟩ 0.7071+0.0000𝑖 50.0000% ↑ 0.0000
%%qsharp
R1Frac(1, 2, qubits[0]);
R1Frac(1, 3, qubits[1]);
dump = qsharp.dump_machine()
dump
Basis State
(|𝜓₁…𝜓ₙ⟩) Amplitude Measurement Probability Phase
|10⟩ 0.5000+0.5000𝑖 50.0000% ↗ 0.7854
|11⟩ 0.2706+0.6533𝑖 50.0000% ↗ 1.1781
# you can print an abbreviated version of the values
print(dump)
STATE:
|10⟩: 0.5000+0.5000𝑖
|11⟩: 0.2706+0.6533𝑖
# you can access the current qubit count
dump.qubit_count
2
# you can access individual states by their index
dump[2]
(0.5+0.5000000000000001j)
dump[3]
(0.27059805007309845+0.6532814824381883j)
CheckZero() 및 CheckAllZero() 작업
CheckZero()
큐 CheckAllZero()
Q# 비트 또는 큐비트 배열의 현재 상태가 $\ket{0}$인지 확인할 수 있는 작업입니다. CheckZero()
는 큐비트가 $\ket{0}$ 상태이고 false
다른 상태에 있으면 반환 true
합니다. CheckAllZero()
는 배열의 모든 큐비트가 $\ket$ 상태이고 false
큐비트가{0} 다른 상태에 있는지를 반환 true
합니다.
import Microsoft.Quantum.Diagnostics.*;
operation Main() : Unit {
use qs = Qubit[2];
X(qs[0]);
if CheckZero(qs[0]) {
Message("X operation failed");
}
else {
Message("X operation succeeded");
}
ResetAll(qs);
if CheckAllZero(qs) {
Message("Reset operation succeeded");
}
else {
Message("Reset operation failed");
}
}
dump_operation() 함수
dump_operation
는 작업 또는 작업 정의 및 사용할 수 있는 여러 큐비트를 사용하고 작업의 출력을 나타내는 복소수의 제곱 행렬을 반환하는 Python 함수입니다.
에서 qsharp.utils
가져옵니다dump_operation
.
import qsharp
from qsharp.utils import dump_operation
다음은 단일 큐비트 ID 게이트와 Hadamard 게이트의 행렬을 인쇄하는 예제입니다.
res = dump_operation("qs => ()", 1)
print(res)
res = dump_operation("qs => H(qs[0])", 1)
print(res)
[[(1+0j), 0j], [0j, (1+0j)]]
[[(0.707107+0j), (0.707107+0j)], [(0.707107+0j), (-0.707107-0j)]]
함수 또는 연산을 정의 qsharp.eval()
한 다음 .dump_operation
앞에서 표현한 단일 큐비트를 로 나타낼 수도 있습니다.
qsharp.eval("operation SingleQ(qs : Qubit[]) : Unit { }")
res = dump_operation("SingleQ", 1)
print(res)
[[(1+0j), 0j], [0j, (1+0j)]]
이 예제에서는 게이트를 Controlled Ry
사용하여 두 번째 큐비트에 회전을 적용합니다.
qsharp.eval ("operation ControlRy(qs : Qubit[]) : Unit {qs[0]; Controlled Ry([qs[0]], (0.5, qs[1]));}")
res = dump_operation("ControlRy", 2)
print(res)
[[(1+0j), 0j, 0j, 0j], [0j, (1+0j), 0j, 0j], [0j, 0j, (0.968912+0j), (-0.247404+0j)], [0j, 0j, (0.247404+0j), (0.968912+0j)]]
다음 코드는 작업을 ApplySWAP
정의 Q# 하고 2큐비트 ID 작업과 함께 행렬을 출력합니다.
qsharp.eval("operation ApplySWAP(qs : Qubit[]) : Unit is Ctl + Adj { SWAP(qs[0], qs[1]); }")
res = dump_operation("qs => ()", 2)
print(res)
res = dump_operation("ApplySWAP", 2)
print(res)
[[(1+0j), 0j, 0j, 0j], [0j, (1+0j), 0j, 0j], [0j, 0j, (1+0j), 0j], [0j, 0j, 0j, (1+0j)]]
[[(1+0j), 0j, 0j, 0j], [0j, 0j, (1+0j), 0j], [0j, (1+0j), 0j, 0j], [0j, 0j, 0j, (1+0j)]]
사용 dump_operation()
중인 테스트 작업의 더 많은 예제는 QDK의 테스트 작업 샘플 페이지에서 찾을 수 있습니다.