Exercício: Criar diferentes estados de superposição com Q#

Concluído

Nas unidades anteriores, você aprendeu sobre a superposição e a notação Dirac. Chega de teoria por enquanto! Vamos escrever um código para explorar a superposição em Q#.

Nesta unidade, você cria estados de superposição quântica em Q# e explora a função de probabilidade nos resultados da medida. Você também usa a DumpMachine função em Q# para examinar como o estado de um sistema muda durante uma computação quântica.

Crie um novo arquivo em Q#

  1. Abra o VS Code (Visual Studio Code).
  2. Abra o menu Arquivo e escolha Novo Arquivo de Texto para criar um novo arquivo.
  3. Salve o arquivo como Main.qs.

Introdução à superposição

Vamos começar com um programa de Q# simples que usa um qubit em um estado de superposição para gerar um valor de bit aleatório, 0 ou 1. Em nosso código, usamos a DumpMachine função para ver o estado do qubit em diferentes pontos do programa.

  1. Copie e cole o seguinte código no arquivo Main.qs :

    import Std.Diagnostics.*;
    
    operation Main() : Result {
        use q = Qubit();
        Message("Initialized qubit:");
        DumpMachine(); // First dump
        Message(" ");
        H(q);
        Message("Qubit after applying H:");
        DumpMachine(); // Second dump
        Message(" ");
        let randomBit = M(q);
        Message("Qubit after the measurement:");
        DumpMachine(); // Third dump
        Message(" ");
        Reset(q);
        Message("Qubit after resetting:");
        DumpMachine(); // Fourth dump
        Message(" ");
        return randomBit;
    }
    
  2. Para executar seu programa no simulador interno, escolha a lente Executar código acima da Main operação ou pressione Ctrl + F5. A saída é exibida no console de depuração.

  3. Examine o console de depuração para localizar o resultado da medida, seja Zero ou One.

A DumpMachine função cria uma tabela de informações que descreve o estado do sistema quântico, que nesse caso é um único qubit. As informações de DumpMachine incluem a amplitude de probabilidade, a probabilidade de medição e a fase em radianos para cada estado de base.

Seu código chama a DumpMachine função quatro vezes:

  • Depois de alocar o qubit
  • Depois de colocar o qubit em um estado de superposição
  • Depois de medir o estado do qubit
  • Depois de redefinir o qubit

Vamos examinar a saída de cada chamada para DumpMachine:

  • Qubit inicializado: Quando você aloca um qubit com a use instrução, o qubit sempre começa no estado $|0\rangle$.

    Initialized qubit:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |0⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    
  • Qubit após aplicar H: Após aplicar a operação H, o qubit estará em um estado de superposição igual, $|\psi\rangle=\frac1{\sqrt2} |0\rangle + \frac1{\sqrt2} |1\rangle$.

    Qubit after applying H:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |0⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
       |1⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
    
    
  • Qubit após a medida: Depois de medir o qubit, o resultado é Zero ou One, e o qubit está totalmente no estado que você mediu.

    Qubit after the measurement:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |1⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    

    Observação

    A saída de DumpMachine após a medição pode diferir da saída de exemplo, pois há 50% de chance de medir cada estado. As probabilidades dos resultados são determinísticas, mas o resultado de uma medida individual não é.

  • Qubit após a redefinição: A Reset operação redefine o qubit para o estado $|0\rangle$ para que ele possa ser usado novamente para cálculos futuros.

    Qubit after resetting:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |0⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    

Explorar outros estados de superposição

Agora que você sabe como inspecionar o estado de um sistema qubit com DumpMachine, vamos explorar outras operações que colocam o sistema em diferentes tipos de estados de superposição.

Gerador de bits aleatórios atual produz Zero ou One com uma probabilidade de 50%. No próximo exemplo, as probabilidades não são iguais.

Gerador de bit aleatório distorcido

Suponha que você queira criar um gerador de bits aleatório que seja distorcido, o que significa que a probabilidade de obter Zero é diferente da probabilidade de obter One.

Por exemplo, você deseja que o resultado Zero ocorra com probabilidade $P$ e o resultado One ocorra com probabilidade $1 - P$. Aqui está um estado de qubit válido que produz um gerador de bits aleatório:

$$|\psi\rangle=\sqrt{P}|0\rangle+\sqrt{1 - P}|1\rangle$$

Para este estado $|\psi\rangle$, $\alpha=\sqrt{P}$ e $\beta=\sqrt{1 - P}$ são as amplitudes de probabilidade dos estados base $|0\rangle$ e $|1\rangle$, respectivamente.

Para obter esse estado, você pode aplicar sequencialmente o operador $R_y(2\cos^{-1}\sqrt{P})$ a um qubit que começa no estado $|0\rangle$. Para obter esse resultado no Q#, use o Ry da biblioteca padrão.

Dica

Para saber mais sobre a matemática por trás de operações de qubit único, confira o tutorial sobre portas de Qubit Único no Quantum Katas.

Para criar um estado de superposição distorcido em Q#, siga estas etapas:

  1. Substitua todo o código em Main.qs pelo exemplo a seguir e salve o arquivo. Este exemplo escolhe $\alpha$ para ser aproximadamente $\frac13$.

    import Std.Diagnostics.*;
    import Std.Math.*;
    
    operation Main() : Result {
        use q = Qubit();
        let P = 0.333333; // P is 1/3
        Ry(2.0 * ArcCos(Sqrt(P)), q);
        Message("The qubit is in the desired state.");
        DumpMachine(); // Dump the state of the qubit 
        Message("Your skewed random bit is:");
        let skewedrandomBit = M(q);
        Reset(q);
        return skewedrandomBit;
    }
    
  2. Para executar seu programa no simulador interno, escolha a lente Executar código acima da Main operação ou pressione Ctrl + F5. A saída é exibida no console de depuração.

  3. Examine a saída de DumpMachine e o resultado da sua medição. Por exemplo, a saída é semelhante à seguinte:

    The qubit is in the desired state.
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |0⟩ |  0.5773+0.0000𝑖 |    33.3333% |   0.0000
       |1⟩ |  0.8165+0.0000𝑖 |    66.6667% |   0.0000
    
    Your skewed random bit is:
    
    One
    

Observe que a probabilidade de um Zero resultado de medida é de cerca de 33,33% e a probabilidade de um One resultado é de cerca de 66,67%. Esse gerador de bits aleatório é distorcido para One.

Observação

A saída do resultado da medida pode ser diferente da saída de exemplo porque o gerador de bits aleatório é probabilístico. As probabilidades dos resultados são determinísticas, mas o resultado de uma medida individual não é.

Superposição de vários qubits

Até agora, consideramos apenas sistemas de qubit único. Mas um bom computador quântico precisa de muitos qubits para executar cálculos úteis. Como os estados quânticos e a superposição funcionam quando nosso sistema tem mais de um qubit?

Por exemplo, considere um sistema de três qubits. Cada qubit pode ter um valor de 0 ou 1 ao medi-los, portanto, há oito estados possíveis em que você pode encontrar o sistema em:

$$|000\rangle,|001\rangle,|010\rangle,|011\rangle,|100\rangle,|101\rangle, |110\rangle,|111\rangle $$

Há oito estados possíveis para esse sistema porque cada qubit pode ser independentemente um estado 0 ou 1 quando fazemos uma medida. Em geral, o número de estados possíveis é igual a $2^n$, onde $n$ é o número de qubits.

Assim como acontece com um único qubit, um estado arbitrário de superposição para o sistema de 3 qubits é representado como uma soma ponderada desses oito estados, em que os pesos são as amplitudes de probabilidade:

$$|\psi\rangle=\alpha_0|000\rangle+\alpha_1|001\rangle+\alpha_2|010\rangle+\alpha_3|011\rangle+\alpha_4|100\rangle+\alpha_5|101\rangle+\alpha_6 |110\rangle+\alpha_7|111\rangle$$

Mais uma vez, as amplitudes $\alpha_i$ são números complexos que atendem à condição $\sum\limits_{i=0}^{i=7}|\alpha_i|^2=1$.

Por exemplo, você pode colocar qubits em uma superposição uniforme aplicando H a cada um deles. Em seguida, você pode usar essa superposição uniforme para criar um gerador de número aleatório quântico que gera números de três bits em vez de números de um bit:

Estado base Número
$\ket{000}$ 0
$\ket{001}$ 4
$\ket{010}$ 2
$\ket{011}$ 6
$\ket{100}$ 1
$\ket{101}$ 5
$\ket{110}$ 3
$\ket{111}$ 7

Observação

A maneira padrão de gravar cadeias de caracteres de bits é ter o menor dígito à direita e o maior dígito à esquerda, assim como com números decimais regulares. Em Q# (e em muitas outras linguagens de programação quântica), a ordem é invertida para que o menor dígito esteja à esquerda e o maior dígito esteja à direita. Como a DumpMachine função exibe estados quânticos na ordem padrão, os inteiros decimais aos quais os estados correspondem não são ordenados sequencialmente de 0 a $n-1$.

Para criar esse tipo de gerador de número aleatório, siga estas etapas:

  1. Substitua o código em Main.qs pelo exemplo a seguir e salve o arquivo:

    import Std.Diagnostics.*;
    import Std.Convert.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register in a uniform superposition: ");
        DumpMachine();
        let result = MeasureEachZ(qubits);
        Message("Measuring the qubits collapses the superposition to a basis state.");
        DumpMachine();
        ResetAll(qubits);
        return ResultArrayAsInt(result);
    }
    
  2. Para executar seu programa no simulador interno, escolha a lente Executar código acima da Main operação ou pressione Ctrl + F5. A saída é exibida no console de depuração.

  3. Examine a saída de DumpMachine e o resultado da sua medição. Por exemplo, a saída é semelhante à seguinte:

    The qubit register in a uniform superposition: 
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |000⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |001⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |010⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |011⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |100⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |101⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |110⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |111⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
    
    Measuring the qubits collapses the superposition to a basis state.
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |011⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    
    6
    

    Observação

    Sua saída provavelmente tem um resultado diferente da saída de exemplo porque o gerador de número aleatório é probabilístico. As probabilidades dos resultados são determinísticas, mas o resultado de uma medida individual não é.

Para trabalhar com vários qubits, seu código Q# tem as seguintes modificações:

  • A variável qubits agora representa uma matriz de Qubit que tem um comprimento igual a três.
  • As operações ApplyToEach e MeasureEachZ aplicar operações quânticas a vários qubits com apenas uma linha de código. As bibliotecas de Q# oferecem muitas funções e operações que simplificam a programação quântica para você.
  • A função ResultArrayAsInt da Std.Convert biblioteca transforma a matriz binária Result em um inteiro decimal.

A saída de DumpMachine mostra que o ato de medição colapsa o estado de superposição em um dos oito estados de base possíveis, assim como ocorre com um único qubit. Por exemplo, se você obtiver o resultado 6, significa que o estado do sistema caiu para $|011\rangle$.

Agora vamos dar uma olhada mais profunda em como o sistema muda à medida que medimos cada qubit. O código anterior usou a MeasureEachZ operação para medir todos os três qubits ao mesmo tempo. Em vez disso, vamos usar um for loop para medir os qubits um de cada vez e usar DumpMachine para exibir o estado do sistema após cada medida.

  1. Substitua o código em Main.qs pelo exemplo a seguir e salve o arquivo:

    import Std.Diagnostics.*;
    import Std.Convert.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register is in a uniform superposition: ");
        DumpMachine();
        mutable results = [];
        for q in qubits {
            Message(" ");
            results += [M(q)];
            DumpMachine();
        }
        ResetAll(qubits);
        Message("Your random number is: ");
        return ResultArrayAsInt(results);
    }
    
  2. Para executar seu programa no simulador interno, escolha a lente Executar código acima da Main operação ou pressione Ctrl + F5. Sua saída aparece no console de depuração.

  3. Examine a saída de DumpMachine e o resultado da sua medição.

A saída mostra como cada medida consecutiva altera o estado quântico e, portanto, as probabilidades para obter cada resultado. Por exemplo, vamos examinar cada parte da saída caso o resultado seja 5:

  • Preparação de estado; o sistema está em um estado de superposição igual depois que se aplica H a cada qubit.

    The qubit register is in a uniform superposition: 
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |000⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |001⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |010⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |011⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |100⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |101⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |110⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |111⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
    
  • Primeira medida: o resultado é One para a primeira medida, portanto, agora os únicos estados possíveis em que o sistema pode acabar são os estados em que o bit mais à esquerda é 1. As amplitudes dos estados onde o qubit mais à esquerda é 0 desapareceram, e as probabilidades dos estados possíveis restantes aumentam de 12,5% para 25,0% de modo que a soma das probabilidades permaneça 100%.

     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |100⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
     |101⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
     |110⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
     |111⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
    
  • Segunda medida: o resultado é Zero para a segunda medida, portanto, agora os únicos estados possíveis em que o sistema pode acabar são os estados em que os dois bits mais à esquerda são 10. Agora ficamos com apenas dois resultados possíveis quando medimos o terceiro qubit, com uma probabilidade de 50% para cada resultado.

     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |100⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
     |101⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
    
  • Terceira medida: na terceira medida, o resultado é One. O sistema é totalmente medido e, portanto, não está mais em um estado de superposição, conforme o esperado.

     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |101⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    
    Your random number is: 
    
    5
    

Com o Q#, você pode criar um sistema de qubits, colocar os qubits em um estado de superposição e examinar como o sistema muda conforme você aplica operações quânticas ou faz medidas.