다음을 통해 공유


양자 코드를 디버그하고 테스트하는 방법

테스트 및 디버깅은 양자 프로그래밍에서 클래식 프로그래밍과 마찬가지로 중요합니다. 이 문서에서는 VS Code(Visual Studio Code) 및 Jupyter Notebook에서 Azure Quantum Development Kit (QDK)를 사용하여 양자 프로그램을 디버그하고 테스트하는 방법을 설명합니다.

양자 코드 디버그

QDK는 코드를 디버그하는 몇 가지 도구를 제공합니다. VS Code에서 Q# 또는 OpenQASM 프로그램을 작성하거나 여는 경우, VS Code 디버거를 사용하여 여러분의 프로그램에 중단점을 설정하고 코드를 분석할 수 있습니다. 또한 QDK는 프로그램의 여러 지점에서 정보를 가져오는 데 사용할 수 있는 덤프 함수 집합을 제공합니다.

VS Code 디버거를 사용하는 방법

VS Code의 QDK 확장을 사용하면 디버거를 사용하여 코드를 단계별로 실행하고, 각 함수 또는 작업으로 이동하고, 지역 변수의 값을 추적하고, 큐비트의 양자 상태를 따를 수 있습니다.

다음 예제에서는 프로그램에서 디버거 Q# 를 사용하는 방법을 보여 줍니다. VS Code 디버거에 대한 자세한 내용은 VS Code 웹 사이트의 디버깅을 참조하세요.

  1. VS Code에서 다음 코드를 사용하여 새 .qs 파일을 만들고 저장합니다.

    import Std.Arrays.*;
    import Std.Convert.*;
    
    operation Main() : Result {
        use qubit = Qubit();
        H(qubit);
        let result = M(qubit);
        Reset(qubit);
        return result;
    }
    
  2. 줄 6 H(qubit)에서 줄 번호의 왼쪽을 클릭하여 중단점을 설정합니다. 빨간색 원이 나타납니다.

  3. 기본 사이드바에서 디버거 아이콘을 선택하여 디버거 창을 연 다음 실행 및 디버그를 선택합니다. 디버거 컨트롤 막대가 나타납니다.

  4. F5 키를 눌러 디버거를 시작하고 중단점으로 계속 진행합니다. 디버거 창의 변수 메뉴에서 양자 상태 드롭다운을 확장하여 큐비트가 $\ket{0}$ 상태로 초기화되었는지 확인합니다.

  5. F11 키를 눌러 작업을 한 단계씩 실행합니다H. H 작업의 소스 코드가 나타납니다. 작업을 단계별로 진행할 때 퀀텀 상태가 중첩으로 변경됩니다H.

  6. F10 키를 눌러 작업을 단계별로 실행합니다M. 양자 상태는 측정 후 $\ket{0}$ 또는 $\ket{1}$로 확인됩니다. 변수는 result지역 아래에도 나타납니다.

  7. F10 키를 다시 눌러 작업을 단계별로 실행합니다Reset. Quantum State가 $\ket{0}$로 다시 설정됩니다.

디버거 탐색을 마쳤으면 *Ctrl+ F5 를 눌러 디버거를 종료합니다.

참고 항목

VS Code 디버거는 Q# (.qs)와 OpenQASM (.qasm) 파일에서만 작동합니다. Jupyter Notebook의 셀에는 Q# VS Code 디버거를 사용할 수 없습니다.

QDK 덤프 함수를 사용하여 디버그하는 방법

QDK는 이러한 함수를 호출할 때 프로그램의 현재 상태에 대한 정보를 덤프하는 여러 Q# Python 함수를 제공합니다. 이러한 덤프 함수의 정보를 사용하여 프로그램이 예상대로 작동하는지 확인합니다.

Q# DumpMachine 함수

DumpMachine Q# 는 프로그램이 실행되면 큐비트 시스템의 현재 상태에 대한 정보를 콘솔에 덤프할 수 있는 함수입니다. DumpMachine 는 런타임 중에 프로그램을 중지하거나 중단하지 않습니다.

다음 예제에서는 DumpMachine 프로그램의 두 지점에서 Q#을 호출하고 출력 결과를 분석합니다.

  1. VS Code에서 다음 코드를 사용하여 새 .qs 파일을 만들고 저장합니다.

    import Std.Diagnostics.*;
    
    operation Main() : 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);
    }
    
  2. Ctrl + Shift + Y를 눌러 디버그 콘솔을 엽니다.

  3. Ctrl+F5를 눌러 프로그램을 실행합니다. DumpMachine의 다음 출력이 디버그 콘솔에 나타납니다.

    Basis | Amplitude      | Probability | Phase
    -----------------------------------------------
     |00⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
     |01⟩ | −0.7071+0.0000𝑖 |    50.0000% |  -3.1416
    
    Basis | Amplitude      | Probability | Phase
    -----------------------------------------------
     |00⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
     |01⟩ | −0.6533−0.2706𝑖 |    50.0000% |  -2.7489
    

출력 DumpMachine 은 각 게이트 집합 이후에 큐비트 시스템의 상태가 어떻게 변하는지 보여줍니다.

참고 항목

출력 DumpMachine은 big-endian 순서를 사용합니다.

Python dump_machine 함수

함수는 dump_machine Python 패키지의 qsharp 함수입니다. 이 함수는 현재 할당된 큐비트 수와 큐비트 시스템의 스파스 상태 진폭을 포함하는 사전을 반환합니다.

다음 예제에서는 이전 DumpMachine 예제와 동일한 프로그램을 실행하지만 파일 대신 .qs Jupyter Notebook에서 실행합니다.

  1. VS Code에서 Ctrl + Shift + P 를 눌러 명령 팔레트를 엽니다.

  2. 만들기: 새 Jupyter Notebook을 입력하고 Enter 키를 누릅니다. 새 Jupyter Notebook 탭이 열립니다.

  3. 첫 번째 셀에서 다음 코드를 복사하고 실행합니다.

    from qdk import qsharp 
    
  4. 새 코드 셀을 만든 다음, 다음 Q# 코드를 복사하여 실행합니다.

    %%qsharp
    
    use qubits = Qubit[2];
    X(qubits[0]);
    H(qubits[1]);
    
  5. 새로운 코드 셀을 만듭니다. 다음 Python 코드를 복사하여 실행하여 프로그램의 이 시점에서 큐비트 상태를 확인합니다.

    dump = qsharp.dump_machine()
    dump
    

    함수는 dump_machine 다음 출력을 표시합니다.

    Basis State
    (|𝜓₁…𝜓ₙ⟩)  Amplitude       Measurement Probability  Phase
    |10⟩       0.7071+0.0000𝑖   50.0000%                 ↑  0.0000
    |11⟩       0.7071+0.0000𝑖   50.0000%                 ↑  0.0000
    
  6. 새 코드 셀을 만든 다음, 다음 Q# 코드를 복사하여 실행합니다.

    %%qsharp
    
    R1Frac(1, 2, qubits[0]);
    R1Frac(1, 3, qubits[1]);
    
  7. 새로운 코드 셀을 만듭니다. 다음 Python 코드를 복사하여 실행하여 프로그램의 이 시점에서 큐비트 상태를 확인합니다.

    dump = qsharp.dump_machine()
    dump
    

    함수는 dump_machine 다음 출력을 표시합니다.

    Basis State
    (|𝜓₁…𝜓ₙ⟩)  Amplitude      Measurement Probability  Phase
    |10⟩       0.5000+0.5000𝑖  50.0000%                 ↗  0.7854
    |11⟩       0.2706+0.6533𝑖  50.0000%                 ↗  1.1781
    
  8. 약식 버전의 dump_machine 출력을 인쇄하려면 새 셀을 만들고 다음 Python 코드를 실행합니다.

    print(dump)
    
  9. 시스템의 총 큐비트 수를 얻으려면 새 코드 셀을 만들고 다음 Python 코드를 실행합니다.

    dump.qubit_count
    
  10. 0이 아닌 진폭이 있는 개별 큐비트 상태의 진폭에 액세스할 수 있습니다. 예를 들어 새 코드 셀을 만들고 다음 Python 코드를 실행하여 $\ket$ 및 $\ket{10}{11}$ 상태에 대한 개별 진폭을 가져옵니다.

    print(dump[2])
    print(dump[3])
    

dump_operation 함수

함수는 dump_operation Python 패키지의 qsharp.utils 함수입니다. 이 함수는 작업 또는 작업 정의를 문자열로 Q# 입력받고, 작업에 사용되는 큐비트 수를 입력받습니다. 출력 dump_operation 은 지정된 양자 연산에 해당하는 복소수의 제곱 행렬을 나타내는 중첩된 목록입니다. 행렬 값은 계산 기준이며 각 하위 목록은 행렬의 행을 나타냅니다.

다음 예제에서는 1큐비트 및 2큐비트 시스템에 대한 정보를 표시하는 데 사용합니다 dump_operation .

  1. VS Code에서 Ctrl + Shift + P 를 눌러 명령 팔레트를 엽니다.

  2. 만들기: 새 Jupyter Notebook을 입력하고 Enter 키를 누릅니다. 새 Jupyter Notebook 탭이 열립니다.

  3. 첫 번째 셀에서 다음 코드를 복사하고 실행합니다.

    from qdk import qsharp
    from qsharp.utils import dump_operation
    
  4. 단일 큐비트 게이트의 행렬 요소를 표시하려면 큐비트 수에 대해 1을 호출 dump_operation 하고 전달합니다. 예를 들어 새 코드 셀에서 다음 Python 코드를 복사하여 실행하여 ID 게이트 및 Hadamard 게이트에 대한 행렬 요소를 가져옵니다.

    res = dump_operation("qs => ()", 1)
    print("Single-qubit identity gate:\n", res)
    print()
    
    res = dump_operation("qs => H(qs[0])", 1)
    print("Single-qubit Hadamard gate:\n", res)
    
  5. 함수를 호출한 다음 qsharp.eval에서 작업을 Q# 참조하여 dump_operation 동일한 결과를 얻을 수도 있습니다. 예를 들어 새 코드 셀을 만든 다음, 다음 Python 코드를 복사하여 실행하여 단일 큐비트 Hadamard 게이트에 대한 행렬 요소를 인쇄합니다.

    qsharp.eval("operation SingleH(qs : Qubit[]) : Unit { H(qs[0]) }")
    
    res = dump_operation("SingleH", 1)
    print("Single-qubit Hadamard gate:\n", res)
    
  6. 2큐비트 게이트의 행렬 요소를 표시하려면 큐비트 수에 대해 2를 호출 dump_operation 하고 전달합니다. 예를 들어 새 코드 셀에서 다음 Python 코드를 복사하여 실행하여 두 번째 큐비트가 큐비트 target 인 제어된 Ry 작업의 행렬 요소를 가져옵니다.

    qsharp.eval ("operation ControlRy(qs : Qubit[]) : Unit { Controlled Ry([qs[0]], (0.5, qs[1])); }")
    
    res = dump_operation("ControlRy", 2)
    print("Controlled Ry rotation gate:\n", res)
    

코드를 dump_operation테스트하고 디버그하는 방법에 대한 자세한 예제는 QDK 샘플에서 테스트 작업을 참조하세요.

양자 코드 테스트

QDK는 코드가 실행될 때 테스트하는 데 사용할 수 있는 몇 가지 Q# 함수와 작업을 제공합니다. 프로그램에 대한 Q# 단위 테스트를 작성할 수도 있습니다.

fail

이 표현은 fail 귀하의 프로그램을 즉시 종료합니다. 테스트를 코드에 통합하려면 조건문 내의 식을 사용합니다 fail .

다음 예제에서는 문을 사용하여 fail 큐비트 배열에 정확히 3개의 큐비트가 포함되어 있음을 테스트합니다. 테스트가 통과되지 않으면 프로그램이 오류 메시지로 끝납니다.

  1. VS Code에서 다음 코드를 사용하여 새 .qs 파일을 만들고 저장합니다.

    operation Main() : Unit {
        use qs = Qubit[6];
        let n_qubits = Length(qs);
    
        if n_qubits != 3 {
            fail $"The system should have 3 qubits, not {n_qubits}.";
        }  
    }
    
  2. Ctrl+F5를 눌러 프로그램을 실행합니다. 프로그램이 실패하고 디버그 콘솔에 다음 출력이 표시됩니다.

    Error: program failed: The system should have 3 qubits, not 6.
    
  3. 코드를 Qubit[6] 편집하고 Qubit[3]파일을 저장한 다음 Ctrl+F5 를 눌러 프로그램을 다시 실행합니다. 테스트가 통과하기 때문에 프로그램이 오류 없이 실행됩니다.

Fact 함수

네임스페이스의 Q#Fact 함수를 Std.Diagnostics 사용하여 코드를 테스트할 수도 있습니다. 이 함수는 Fact 부울 식과 오류 메시지 문자열을 사용합니다. 부울 식이 true이면 테스트가 통과되고 프로그램이 계속 실행됩니다. 부울 식이 false Fact 이면 프로그램을 종료하고 오류 메시지를 표시합니다.

이전 코드에서 동일한 배열 길이 테스트를 수행하려면 Fact 함수를 사용하여 다음 단계를 수행합니다.

  1. VS Code에서 다음 코드를 사용하여 새 .qs 파일을 만들고 저장합니다.

    import Std.Diagnostics.Fact;
    
    operation Main() : Unit {
        use qs = Qubit[6];
        let n_qubits = Length(qs);
    
        Fact(n_qubits == 3,  $"The system should have 3 qubits, not {n_qubits}.")
    }
    
  2. Ctrl+F5를 눌러 프로그램을 실행합니다. 테스트 조건이 Fact 전달되지 않고 디버그 콘솔에 오류 메시지가 나타납니다.

  3. 코드를 Qubit[6] 편집하고 Qubit[3]파일을 저장한 다음 Ctrl+F5 를 눌러 프로그램을 다시 실행합니다. 테스트 조건이 Fact 통과되고 프로그램이 오류 없이 실행됩니다.

Q# 주석으로 @Test() 단위 테스트를 작성하세요.

Q# 프로그램에서 호출 가능(함수 또는 작업)에 주석을 적용 @Test() 하여 호출 가능 항목을 단위 테스트로 전환할 수 있습니다. 이러한 단위 테스트는 VS Code의 테스트 메뉴에 표시되므로 이 VS Code 기능을 활용할 수 있습니다. 호출 가능 항목이 입력 매개 변수를 취하지 않는 경우에만 호출 가능을 단위 테스트로 전환할 수 있습니다.

다음 예제에서는 작업에서 배열 길이 테스트 코드를 래핑하고 해당 작업을 단위 테스트로 바꿉니다.

  1. VS Code에서 다음 코드를 사용하여 새 .qs 파일을 만들고 저장합니다.

    import Std.Diagnostics.Fact;
    
    @Test()
    operation TestCase() : Unit {
        use qs = Qubit[3];
        let n_qubits = Length(qs);
    
        Fact(n_qubits == 3, $"The system should have 3 qubits, not {n_qubits}.");
    }
    

    @Test() 작업 정의 이전 줄의 TestCase 주석은 작업을 VS Code 단위 테스트로 전환합니다. 작업 정의 줄에 녹색 화살표가 나타납니다.

  2. 녹색 화살표를 선택하여 테스트 결과를 실행하고 TestCase 보고합니다.

  3. VS Code 테스트 탐색기에서 단위 테스트와 상호 작용하려면 기본 사이드바에서 테스트 flask 아이콘을 선택합니다.

  4. 코드를 Qubit[3] 편집하고 Qubit[6] 단위 테스트를 다시 실행하여 테스트 정보가 어떻게 변경되는지 확인합니다.

프로그램의 진입점 작업 없이 VS Code에서 Q# 단위 테스트를 작성하고 실행할 수 있습니다.

참고 항목

네임스페이 Std.Diagnostics 스의 호출 가능 항목은 QIR 생성과 호환되지 않으므로 시뮬레이터에서 실행하는 코드에 Q# 단위 테스트만 포함됩니다. 코드에서 Q# QIR을 생성하려는 경우 코드에 단위 테스트를 포함하지 마세요.

작업 CheckZeroCheckAllZero

CheckZeroCheckAllZeroQ# 작업은 큐비트 또는 큐비트 배열의 현재 상태가 $\ket{0}$인지 확인합니다. 이 CheckZero 작업은 단일 큐비트를 사용하고 큐비트가 $\kettrue$ 상태인 경우에만 반환 {0} 합니다. 작업은 CheckAllZero 큐비트 배열을 사용하고 배열의 모든 큐비트가 $\kettrue$ 상태인 경우에만 반환 {0} 됩니다. 사용하려면 CheckZeroCheckAllZeroStd.Diagnostics 네임스페이스에서 가져와야 합니다.

다음 예제에서는 두 작업을 모두 사용합니다. CheckZero X 작업은 첫 번째 큐비트를 $\ket{{0}}$ 상태에서 $\ket{{1}}$ 상태로 반전시키는 것을 테스트하고, CheckAllZero 작업은 두 큐비트가 모두 $\ket{{0}}$ 상태로 다시 초기화되는 것을 테스트합니다.

VS Code에서 다음 코드를 사용하여 새 .qs 파일을 만들고 저장한 다음, 프로그램을 실행하고 디버그 콘솔에서 출력을 검사합니다.

import Std.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");
    }
}