Cara men-debug dan menguji kode kuantum Anda

Pengujian dan penelusuran kesalahan sama pentingnya dalam pemrograman kuantum seperti dalam pemrograman klasik. Artikel ini membahas cara men-debug dan menguji program kuantum Anda dengan Microsoft Quantum Development Kit (QDK) di Visual Studio Code (VS Code) dan Jupyter Notebook.

Debug kode kuantum Anda

QDK menyediakan beberapa alat untuk men-debug kode Anda. Jika Anda menulis Q# atau Program OpenQASM di VISUAL Code, maka Anda dapat menggunakan debugger Visual Studio Code untuk mengatur titik henti dalam program Anda dan menganalisis kode Anda. QDK juga menyediakan serangkaian fungsi cadangan yang dapat Anda gunakan untuk mendapatkan informasi di titik yang berbeda dalam program Anda.

Cara menggunakan debugger Visual Studio Code

Dengan ekstensi QDK di VISUAL Code, Anda dapat menggunakan debugger untuk menelusuri kode Anda dan ke setiap fungsi atau operasi, melacak nilai variabel lokal, dan mengikuti status kuantum qubit.

Contoh berikut menunjukkan cara menggunakan debugger dengan Q# program. Untuk informasi lengkap tentang debugger VS Code, lihat Debugging di situs web VS Code.

  1. Di Visual Studio Code, buat dan simpan file baru .qs dengan kode berikut:

    import Std.Arrays.*;
    import Std.Convert.*;
    
    operation Main() : Result {
        use qubit = Qubit();
        H(qubit);
        let result = M(qubit);
        Reset(qubit);
        return result;
    }
    
  2. Pada baris 6, H(qubit), klik di sebelah kiri nomor baris untuk mengatur titik henti. Lingkaran merah ditampilkan.

  3. Di Bilah Sisi Utama, pilih ikon debugger untuk membuka panel debugger, lalu pilih Jalankan dan Debug. Bilah kontrol debugger terbuka.

  4. Tekan F5 untuk memulai debugger dan lanjutkan ke titik henti. Di menu Variabel panel debugger, perluas dropdown Status Quantum untuk melihat bahwa qubit telah diinisialisasi dalam status $\ket{0}$.

  5. Tekan F11 untuk masuk ke H operasi. Kode sumber untuk operasi H muncul. Perhatikan bahwa Quantum State berubah menjadi superposisi saat Anda melangkah melalui operasi H.

  6. Tekan F10 untuk melewati M operasi. Perhatikan bahwa Quantum State berubah menjadi $\ket{0}$ atau $\ket{1}$ setelah pengukuran. Variabel result tercantum di bawah Lokal.

  7. Tekan F10 lagi untuk melangkahi Reset proses. Perhatikan bahwa Status Quantum diatur ulang ke $\ket{0}$.

Setelah selesai menjelajahi debugger, tekan Shift + F5 untuk keluar dari debugger.

Catatan

Debugger Visual Studio Code hanya berfungsi dengan Q# file (.qs) dan OpenQASM (.qasm). Anda tidak dapat menggunakan debugger Visual Studio Code pada Q# sel di Jupyter Notebook.

Cara men-debug dengan fungsi cadangan QDK

QDK menyediakan beberapa fungsi Q# dan fungsi Python yang menampilkan informasi tentang status program Anda saat ini ketika Anda memanggil fungsi-fungsi ini. Gunakan informasi dari fungsi cadangan ini untuk memeriksa apakah program Anda berperilaku seperti yang Anda harapkan.

Fungsi Q#DumpMachine

DumpMachine adalah Q# fungsi yang memungkinkan Anda untuk membuang informasi tentang status sistem qubit saat ini ke konsol saat program Anda berjalan. DumpMachine tidak menghentikan atau mengganggu program Anda selama runtime.

Contoh berikut memanggil DumpMachine di dua titik dalam program Q# dan menjelajahi output.

  1. Di Visual Studio Code, buat dan simpan file baru .qs dengan kode berikut:

    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. Tekan Ctrl + Shift + Y untuk membuka Konsol Debug.

  3. Tekan Ctrl + F5 untuk menjalankan program Anda. Output berikut dari DumpMachine muncul di Konsol Debug:

    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
    

Keluaran dari DumpMachine menunjukkan bagaimana status sistem qubit berubah setelah setiap sekumpulan gerbang.

Catatan

Output dari DumpMachine menggunakan urutan big-endian.

Fungsi Python dump_machine

Fungsi ini dump_machine adalah fungsi dari qsharp paket Python. Fungsi ini mengembalikan jumlah kubit yang dialokasikan saat ini dan daftar yang berisi amplitudo keadaan jarang dari sistem kubit.

Contoh berikut menjalankan program yang sama dengan contoh sebelumnya DumpMachine , tetapi dalam buku catatan Jupyter alih-alih .qs file.

  1. Di Visual Studio Code, tekan Ctrl + Shift + P untuk membuka Palet Perintah.

  2. Masukkan Buat: Jupyter Notebook Baru dan tekan Enter. Tab Jupyter Notebook baru terbuka.

  3. Di sel pertama, salin dan jalankan kode berikut:

    from qdk import qsharp 
    
  4. Buat sel kode baru, lalu salin dan jalankan kode berikut Q# :

    %%qsharp
    
    use qubits = Qubit[2];
    X(qubits[0]);
    H(qubits[1]);
    
  5. Buat sel kode baru. Salin dan jalankan kode Python berikut untuk melihat status qubit pada titik ini dalam program:

    dump = qsharp.dump_machine()
    dump
    

    Fungsi dump_machine ini menampilkan output berikut:

    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. Buat sel kode baru, lalu salin dan jalankan kode berikut Q# :

    %%qsharp
    
    R1Frac(1, 2, qubits[0]);
    R1Frac(1, 3, qubits[1]);
    
  7. Buat sel kode baru. Salin dan jalankan kode Python berikut untuk melihat status qubit pada titik ini dalam program:

    dump = qsharp.dump_machine()
    dump
    

    Fungsi dump_machine ini menampilkan output berikut:

    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. Untuk mencetak versi dump_machine singkat output, buat sel baru dan jalankan kode Python berikut:

    print(dump)
    
  9. Untuk mendapatkan jumlah total qubit dalam sistem, buat sel kode baru dan jalankan kode Python berikut:

    dump.qubit_count
    
  10. Anda dapat mengakses amplitudo masing-masing qubit yang memiliki amplitudo nonzero. Misalnya, buat sel kode baru dan jalankan kode Python berikut untuk mendapatkan amplitudo individual untuk status $\ket{10}$ dan $\ket{11}$:

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

Fungsi dump_operation

Fungsi ini dump_operation adalah fungsi dari qsharp.utils paket Python. Fungsi ini menerima dua input: suatu Q# definisi operasi atau operasi sebagai string, serta jumlah qubit yang digunakan dalam operasi. Output dari dump_operation adalah daftar berlapis yang mewakili matriks persegi bilangan kompleks yang sesuai dengan operasi kuantum yang diberikan. Nilai matriks berada dalam dasar komputasi, dan setiap sublis mewakili baris matriks.

Contoh berikut menggunakan dump_operation untuk menampilkan informasi untuk sistem 1-qubit dan 2-qubit.

  1. Di Visual Studio Code, tekan Ctrl + Shift + P untuk membuka Palet Perintah.

  2. Masukkan Buat: Jupyter Notebook Baru dan tekan Enter. Tab Jupyter Notebook baru terbuka.

  3. Di sel pertama, salin dan jalankan kode berikut:

    from qdk import qsharp
    from qsharp.utils import dump_operation
    
  4. Untuk menampilkan elemen matriks gerbang qubit tunggal, panggil dump_operation dan lewati 1 untuk jumlah qubit. Misalnya, salin dan jalankan kode Python berikut di sel kode baru untuk mendapatkan elemen matriks untuk gerbang identitas dan gerbang 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. Anda juga dapat memanggil fungsi qsharp.eval dan kemudian mereferensikan operasi Q# di dump_operation untuk mendapatkan hasil yang sama. Misalnya, buat sel kode baru, lalu salin dan jalankan kode Python berikut untuk mencetak elemen matriks untuk gerbang Hadamard qubit tunggal:

    qsharp.eval("operation SingleH(qs : Qubit[]) : Unit { H(qs[0]) }")
    
    res = dump_operation("SingleH", 1)
    print("Single-qubit Hadamard gate:\n", res)
    
  6. Untuk menampilkan elemen matriks gerbang dua qubit, panggil dump_operation dan lewati 2 untuk jumlah qubit. Misalnya, salin dan jalankan kode Python berikut di sel kode baru untuk mendapatkan elemen matriks untuk operasi Controlled Ry di mana qubit kedua adalah target qubit:

    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)
    

Untuk contoh selengkapnya tentang cara menguji dan men-debug kode Anda dengan dump_operation, lihat Operasi pengujian dari sampel QDK.

Menguji kode kuantum Anda

QDK menyediakan beberapa Q# fungsi dan operasi yang dapat Anda gunakan untuk menguji kode saat berjalan. Anda juga dapat menulis pengujian unit untuk Q# program.

Ekspresi fail

fail Ungkapan ini langsung mengakhiri program Anda. Untuk menggabungkan pengujian ke dalam kode Anda, gunakan fail ekspresi di dalam pernyataan kondisional.

Contoh berikut menggunakan fail pernyataan untuk menguji bahwa array qubit berisi tepat 3 qubit. Program berakhir dengan pesan kesalahan ketika pengujian tidak lulus.

  1. Di Visual Studio Code, buat dan simpan file baru .qs dengan kode berikut:

    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. Tekan Ctrl + F5 untuk menjalankan program. Program Anda gagal dan output berikut muncul di Konsol Debug:

    Error: program failed: The system should have 3 qubits, not 6.
    
  3. Edit kode Anda dari Qubit[6] ke Qubit[3], simpan file Anda, lalu tekan Ctrl + F5 untuk menjalankan program lagi. Program berjalan tanpa kesalahan karena pengujian lolos.

Fungsi Fact

Anda juga dapat menggunakan fungsi Q#Fact dari Std.Diagnostics namespace untuk menguji kode Anda. Fungsi Fact ini menerima ekspresi Boolean dan string pesan kesalahan. Jika ekspresi Boolean benar, maka pengujian lolos dan program Anda terus berjalan. Jika ekspresi Boolean salah, maka Fact mengakhiri program Anda dan menampilkan pesan kesalahan.

Untuk melakukan pengujian panjang array yang sama dalam kode Anda sebelumnya, tetapi dengan fungsi Fact, ikuti langkah-langkah berikut ini:

  1. Di Visual Studio Code, buat dan simpan file baru .qs dengan kode berikut:

    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. Tekan Ctrl + F5 untuk menjalankan program. Kondisi pengujian di Fact tidak lulus dan pesan kesalahan muncul di Konsol Debug.

  3. Edit kode Anda dari Qubit[6] ke Qubit[3], simpan file Anda, lalu tekan Ctrl + F5 untuk menjalankan program lagi. Kondisi pengujian dalam Fact lulus dan program Anda berjalan tanpa kesalahan.

Tulis Q# pengujian unit dengan @Test() anotasi

Dalam Q# program, Anda dapat menerapkan @Test() anotasi ke pemanggil (fungsi atau operasi) untuk menjadikan pemanggil sebagai uji unit. Pengujian unit ini muncul di menu Pengujian di Visual Studio Code sehingga Anda dapat memanfaatkan fitur Visual Studio Code ini. Anda dapat mengubah panggilan fungsi menjadi uji unit hanya ketika panggilan fungsi tersebut tidak mengambil parameter input.

Contoh berikut membungkus kode uji panjang array dalam operasi dan mengubah operasi tersebut menjadi pengujian unit:

  1. Di Visual Studio Code, buat dan simpan file baru .qs dengan kode berikut:

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

    Anotasi @Test() pada baris sebelum TestCase definisi operasi mengubah operasi menjadi pengujian unit Visual Studio Code. Panah hijau muncul pada baris definisi operasi.

  2. Pilih panah hijau untuk menjalankan TestCase dan melaporkan hasil pengujian.

  3. Untuk berinteraksi dengan pengujian unit Anda di Visual Studio Code Test Explorer, pilih ikon Flask Pengujian di Bilah Sisi Utama.

  4. Edit kode Anda dari Qubit[3] ke Qubit[6] dan jalankan pengujian unit lagi untuk melihat bagaimana informasi pengujian berubah.

Anda dapat menulis dan menjalankan Q# pengujian unit di VS Code tanpa fungsi titik masuk dalam program Anda.

Catatan

Panggilan dari Std.Diagnostics namespace tidak kompatibel dengan generasi QIR, jadi hanya sertakan pengujian unit dalam Q# kode yang Anda jalankan pada simulator. Jika Anda ingin membuat QIR dari kode Anda Q# , maka jangan sertakan pengujian unit dalam kode Anda.

Operasi CheckZero dan CheckAllZero

Operasi CheckZero dan CheckAllZeroQ# memeriksa apakah status qubit atau array qubit saat ini adalah $\ket{0}$. Operasi ini CheckZero mengambil satu qubit dan hanya mengembalikan true ketika qubit berada dalam status $\ket{0}$. Operasi CheckAllZero mengambil array qubit dan hanya mengembalikan true ketika semua qubit dalam array berada dalam status $\ket{0}$. Untuk menggunakan CheckZero dan CheckAllZero, impor dari Std.Diagnostics namespace.

Contoh berikut menggunakan kedua operasi. Pengujian CheckZero memastikan bahwa operasi X membalikkan qubit pertama dari keadaan $\ket{0}$ ke keadaan $\ket{1}$, dan operasi CheckAllZero menguji bahwa kedua qubit direset ke keadaan $\ket{0}$.

Di Visual Studio Code, buat dan simpan file baru .qs dengan kode berikut, lalu jalankan program dan periksa output di Konsol Debug.

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