Partilhar via


Como depurar e testar seu código quântico

Testar e depurar são tão importantes na programação quântica quanto na programação clássica. Este artigo descreve como depurar e testar seus programas quânticos com o Azure Quantum Development Kit (QDK) no Visual Studio Code (VS Code) e Jupyter Notebook.

Depure o código quântico

O QDK fornece várias ferramentas para depurar seu código. Se você escrever Q# ou programas OpenQASM no VS Code, então você pode usar o depurador VS Code para definir pontos de interrupção em seus programas e analisar seu código. O QDK também fornece um conjunto de funções de despejo que você pode usar para obter informações em diferentes pontos do seu programa.

Como usar o depurador VS Code

Com a extensão QDK no VS Code, você pode usar o depurador para percorrer seu código e entrar em cada função ou operação, rastrear os valores das variáveis locais e seguir os estados quânticos dos qubits.

O exemplo a seguir demonstra como usar o depurador com o programa Q#. Para informações completas sobre os depuradores do VS Code, consulte Depuração no site do VS Code.

  1. No VS Code, crie e salve um novo .qs arquivo com o seguinte código:

    import Std.Arrays.*;
    import Std.Convert.*;
    
    operation Main() : Result {
        use qubit = Qubit();
        H(qubit);
        let result = M(qubit);
        Reset(qubit);
        return result;
    }
    
  2. Na linha 6, H(qubit)clique à esquerda do número da linha para definir um ponto de interrupção. Um círculo vermelho aparece.

  3. Na Barra Lateral Primária, escolha o ícone do depurador para abrir o painel do depurador e, em seguida, escolha Executar e Depurar. A barra de controle do depurador é exibida.

  4. Pressione F5 para iniciar o depurador e continuar até o ponto de interrupção. No menu Variáveis do painel do depurador, expanda a lista drop-down Estado Quântico para ver que o qubit foi inicializado no estado $\ket{0}$.

  5. Pressione F11 para entrar na H operação. O código-fonte da H operação é exibido. Observe que o Estado Quântico muda para uma superposição à medida que você passa pela H operação.

  6. Pressione F10 para avançar sobre a M operação. Observe que o Estado Quântico resulta em $\ket{0}$ ou $\ket{1}$ após a medição. A result variável também aparece em Locais.

  7. Pressione F10 novamente para saltar a Reset operação. Observe que o Estado Quântico é redefinido para $\ket{0}$.

Quando terminar de explorar o depurador, pressione *Ctrl + F5 para sair do depurador.

Nota

O depurador VS Code funciona apenas com os Q# (.qs) arquivos e OpenQASM (.qasm). Não é possível usar o depurador VS Code em Q# células no Jupyter Notebook.

Como depurar com funções de exportação de dados QDK

O QDK fornece várias funções e funções Python que despejam informações sobre o estado atual do seu programa quando essas funções são chamadas. Use as informações dessas funções de despejo para verificar se o programa se comporta como esperado.

A Q#DumpMachine função

DumpMachine é uma Q# função que permite despejar informações sobre o estado atual do sistema qubit para o console à medida que o programa é executado. DumpMachine não para ou interrompe o programa durante o tempo de execução.

O exemplo a seguir chama o DumpMachine em dois pontos de um programa Q# e explora a saída.

  1. No VS Code, crie e salve um novo .qs arquivo com o seguinte código:

    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. Pressione Ctrl + Shift + Y para abrir o Console de Depuração.

  3. Pressione Ctrl + F5 para executar o programa. A seguinte saída do DumpMachine aparece no Console de Depuração:

    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
    

A saída de DumpMachine mostra como o estado dos sistemas de qubit muda após cada conjunto de portas.

Nota

A saída de DumpMachine usa ordenação big-endian.

A função Python dump_machine

A dump_machine função é uma função do qsharp pacote Python. Esta função retorna a contagem atual de qubits alocados e um dicionário que contém as amplitudes esparsas do estado do sistema de qubits.

O exemplo a seguir executa o mesmo programa do exemplo anterior DumpMachine, mas num notebook Jupyter em vez de um arquivo .qs.

  1. No VS Code, pressione Ctrl + Shift + P para abrir a Paleta de comandos.

  2. Entre em Create: New Jupyter Notebook e pressione Enter. Uma nova guia Jupyter Notebook é aberta.

  3. Na primeira célula, copie e execute o seguinte código:

    from qdk import qsharp 
    
  4. Crie uma nova célula de código e, em seguida, copie e execute o seguinte Q# código:

    %%qsharp
    
    use qubits = Qubit[2];
    X(qubits[0]);
    H(qubits[1]);
    
  5. Crie uma nova célula de código. Copie e execute o seguinte código Python para visualizar o estado do qubit neste ponto do programa:

    dump = qsharp.dump_machine()
    dump
    

    A dump_machine função exibe a seguinte saída:

    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. Crie uma nova célula de código e, em seguida, copie e execute o seguinte Q# código:

    %%qsharp
    
    R1Frac(1, 2, qubits[0]);
    R1Frac(1, 3, qubits[1]);
    
  7. Crie uma nova célula de código. Copie e execute o seguinte código Python para visualizar o estado do qubit neste ponto do programa:

    dump = qsharp.dump_machine()
    dump
    

    A dump_machine função exibe a seguinte saída:

    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. Para imprimir uma versão abreviada da dump_machine saída, crie uma nova célula e execute o seguinte código Python:

    print(dump)
    
  9. Para obter o número total de qubits no sistema, crie uma nova célula de código e execute o seguinte código Python:

    dump.qubit_count
    
  10. Você pode acessar as amplitudes de estados de qubits individuais que têm amplitude diferente de zero. Por exemplo, crie uma nova célula de código e execute o seguinte código Python para obter as amplitudes individuais para os estados $\ket{10}$ e $\ket{11}$:

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

A função dump_operation

A dump_operation função é uma função do qsharp.utils pacote Python. Esta função usa duas entradas: uma Q# operação ou definição de operação como uma cadeia de caracteres e o número de qubits que são usados na operação. A saída de dump_operation é uma lista aninhada que representa uma matriz quadrada de números complexos correspondente à operação quântica dada. Os valores da matriz estão na base computacional, e cada sublista representa uma linha da matriz.

O exemplo a seguir usa dump_operation para exibir informações para um sistema de 1-qubit e um sistema de 2-qubits.

  1. No VS Code, pressione Ctrl + Shift + P para abrir a Paleta de comandos.

  2. Entre em Create: New Jupyter Notebook e pressione Enter. Uma nova guia Jupyter Notebook é aberta.

  3. Na primeira célula, copie e execute o seguinte código:

    from qdk import qsharp
    from qsharp.utils import dump_operation
    
  4. Para exibir os elementos da matriz de uma porta de qubit único, chame dump_operation e passe 1 para o número de qubits. Por exemplo, copie e execute o seguinte código Python em uma nova célula de código para obter os elementos da matriz para uma porta de identidade e uma porta 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. Você também pode chamar a função qsharp.eval e, em seguida, referenciar a operação Q# em dump_operation para obter o mesmo resultado. Por exemplo, crie uma nova célula de código e, em seguida, copie e execute o seguinte código Python para imprimir os elementos da matriz para um portão Hadamard de qubit único:

    qsharp.eval("operation SingleH(qs : Qubit[]) : Unit { H(qs[0]) }")
    
    res = dump_operation("SingleH", 1)
    print("Single-qubit Hadamard gate:\n", res)
    
  6. Para exibir os elementos da matriz de uma porta de dois qubits, chame dump_operation e passe 2 para o número de qubits. Por exemplo, copie e execute o seguinte código Python em uma nova célula de código para obter os elementos de matriz para uma operação Ry controlada onde o segundo qubit é o 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)
    

Para obter mais exemplos de como testar e depurar o código com dump_operation, consulte Testar operações dos exemplos do QDK.

Teste seu código quântico

O QDK fornece várias Q# funções e operações que você pode usar para testar seu código enquanto ele é executado. Você também pode escrever testes de unidade para Q# programas.

A fail expressão

A fail expressão termina imediatamente o seu programa. Para incorporar testes no seu código, use as expressões fail dentro de instruções condicionais.

O exemplo a seguir usa uma fail instrução para testar se uma matriz de qubit contém exatamente 3 qubits. O programa termina com uma mensagem de erro quando o teste não passa.

  1. No VS Code, crie e salve um novo .qs arquivo com o seguinte código:

    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. Pressione Ctrl + F5 para executar o programa. O programa falha e a seguinte saída aparece no Console de Depuração:

    Error: program failed: The system should have 3 qubits, not 6.
    
  3. Edite o código de Qubit[6] para Qubit[3], salve o arquivo e pressione Ctrl + F5 para executar o programa novamente. O programa é executado sem erro porque o teste passa.

A função Fact

Você também pode usar a Q#Fact função do Std.Diagnostics namespace para testar seu código. A Fact função usa uma expressão booleana e uma cadeia de caracteres de mensagem de erro en. Se a expressão booleana for verdadeira, o teste passa e o programa continua a ser executado. Se a expressão booleana for falsa, encerra Fact o programa e exibe a mensagem de erro.

Para executar o mesmo teste de comprimento de matriz em seu código anterior, mas com a função Fact, execute estas etapas:

  1. No VS Code, crie e salve um novo .qs arquivo com o seguinte código:

    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. Pressione Ctrl + F5 para executar o programa. A condição de teste em Fact não passa e a mensagem de erro aparece no Console de Depuração.

  3. Edite o código de Qubit[6] para Qubit[3], salve o arquivo e pressione Ctrl + F5 para executar o programa novamente. A condição de teste em Fact passa e o seu programa é executado sem um erro.

Escrever Q# testes de unidade com a @Test() anotação

Em Q# programas, pode-se aplicar a anotação @Test() a um callable (função ou operação) para transformar o callable em um teste de unidade. Esses testes de unidades aparecem no menu Teste no VS Code para que você possa aproveitar esse recurso do VS Code. Você pode transformar um chamável em um teste de unidade somente quando o chamável não aceita parâmetros de entrada.

O exemplo a seguir encapsula o código de teste de comprimento de matriz em uma operação e transforma essa operação em um teste de unidade:

  1. No VS Code, crie e salve um novo .qs arquivo com o seguinte código:

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

    A anotação @Test() na linha antes da definição da operação TestCase converte a operação num teste de unidade do VS Code. Uma seta verde aparece na linha de definição da operação.

  2. Escolha a seta verde para executar TestCase e relatar os resultados do teste.

  3. Para interagir com seus testes de unidades no VS Code Test Explorer, escolha o ícone Testing flask na Barra lateral primária.

  4. Edite o seu código de Qubit[3] para Qubit[6] e execute o teste de unidade novamente para ver como as informações do teste mudam.

Você pode escrever e executar Q# testes de unidade no VS Code sem uma operação de ponto de entrada no seu programa.

Nota

Os callables do namespace Std.Diagnostics não são compatíveis com a geração de QIR, pelo que deve incluir apenas testes de unidade no código Q# que é executado em simuladores. Se você quiser gerar QIR a partir do seu Q# código, não inclua testes de unidade no seu código.

As operações CheckZero e CheckAllZero

As operações CheckZero e CheckAllZeroQ# verificam se o estado atual de um qubit ou conjunto de qubits é $\ket{0}$. A CheckZero operação usa um único qubit e retorna true somente quando o qubit está no estado $\ket{0}$. As CheckAllZero operações usam uma matriz de qubit e retornam true somente quando todos os qubits na matriz estão no estado $\ket{0}$. Para usar CheckZero e CheckAllZero, importe-os do namespace Std.Diagnostics.

O exemplo a seguir usa ambas as operações. Os CheckZero testes que a X operação altera o primeiro qubit do estado $\ket{0}$ para o estado $\ket{1}$, e a CheckAllZero operação testa que ambos os qubits são redefinidos para o estado $\ket{0}$.

No VS Code, crie e salve um novo .qs arquivo com o código a seguir, execute o programa e examine a saída no Console de Depuração.

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