Partilhar via


Tutorial: Explore o emaranhamento quântico com Q#

Neste tutorial, você escreve um Q# programa que manipula e mede qubits e demonstra os efeitos de sobreposição e emaranhamento. Você prepara dois qubits em um estado quântico específico, aprende a operar em qubits para Q# mudar seu estado e demonstra os efeitos da superposição e do emaranhamento. Você constrói seu Q# programa peça por peça para introduzir estados, operações e medições de qubit.

Aqui estão alguns conceitos-chave para entender antes de começar:

  • Onde os bits clássicos possuem um único valor binário, como 0 ou 1, o estado de um qubit pode estar em uma superposição de dois estados quânticos, 0 e 1. Cada estado quântico possível tem uma amplitude de probabilidade associada.
  • O ato de medir um qubit produz um resultado binário com uma certa probabilidade, e muda o estado do qubit fora da superposição.
  • Vários qubits podem ser emaranhados de tal forma que não podem ser descritos independentemente uns dos outros. Ou seja, o que quer que aconteça com um qubit em um par emaranhado também acontece com o outro qubit.

Neste tutorial, irá aprender a:

  • Crie Q# operações para inicializar um qubit para um estado desejado.
  • Coloque um qubit em superposição.
  • Enredar um par de qubits.
  • Meça um qubit e observe os resultados.

Gorjeta

Se você quiser acelerar sua jornada de computação quântica, confira Código com o Azure Quantum, um recurso exclusivo do site do Azure Quantum. Aqui, você pode executar amostras internas Q# ou seus próprios Q# programas, gerar novo Q# código a partir de seus prompts, abrir e executar seu código no VS Code for the Web com um clique e fazer perguntas ao Copilot sobre computação quântica.

Pré-requisitos

Para executar o exemplo de código no Copilot para Azure Quantum, você precisa:

  • Uma conta de email da Microsoft (MSA).

Para obter mais informações sobre o Copilot, consulte Explore Azure Quantum.

Inicializar um qubit para um estado conhecido

A primeira etapa é definir uma Q# operação que inicializa um qubit para um estado conhecido. Esta operação pode ser chamada para definir um qubit para um estado clássico, o que significa que, quando medido, ele retorna Zero 100% do tempo ou retorna One 100% do tempo. A medição de um qubit retorna um Q# tipo Result, que só pode ter um valor de Zero ou One.

Abra o Copilot para Azure Quantum e copie o código a seguir na janela do editor de código. Não selecione Executar ainda; Você executará o código mais adiante no tutorial.

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

operation SetQubitState(desired : Result, target : Qubit) : Unit {
    if desired != M(target) {
        X(target);
    }
}

O exemplo de código apresenta duas operações M padrão e X, que transformam o estado de um qubit.

A SetQubitState operação:

  1. Usa dois parâmetros: um tipo Result, chamado desired, que representa o estado desejado para o qubit estar em (Zero ou One), e um tipo Qubit.
  2. Executa uma operação de medição, M, que mede o estado do qubit (Zero ou One) e compara o resultado com o valor especificado em desired.
  3. Se a medição não corresponder ao valor comparado, ela executa uma X operação, que inverte o estado do qubit para onde as probabilidades de uma medição retornam Zero e One são invertidas. Desta forma, SetQubitState sempre coloca o qubit alvo no estado desejado.

Escrever uma operação de teste para testar o estado Bell

Em seguida, para demonstrar o efeito da SetQubitState operação, crie outra operação chamada Main. Esta operação irá alocar dois qubits, chamar SetQubitState para definir o primeiro qubit para um estado conhecido e, em seguida, medir os qubits para ver os resultados.

Copie o código a seguir na janela do editor de código, abaixo da SetQubitState operação.

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}

No código, as count variáveis e initial são definidas como 1000 e One respectivamente. Isso inicializa o primeiro qubit e One mede cada qubit 1000 vezes.

A Mainoperação:

  1. Define variáveis para o contador e o estado qubit inicial.
  2. Chama a use instrução para inicializar dois qubits.
  3. Loops para count iterações. Para cada loop,
    1. Chamadas SetQubitState para definir um valor especificado initial no primeiro qubit.
    2. Chama SetQubitState novamente para definir o segundo qubit para um Zero estado.
    3. Usa a M operação para medir cada qubit.
    4. Armazena o número de medidas para cada qubit que retornam One.
  4. Depois que o loop é concluído, ele chama SetQubitState novamente para redefinir os qubits para um estado conhecido (Zero) para permitir que outros aloquem os qubits em um estado conhecido. A redefinição é exigida use pela instrução.
  5. Finalmente, ele usa a Message função para imprimir os resultados nas janelas de saída do Copilot antes de retornar os resultados.

Execute o código no Copilot para Azure Quantum

Antes de passar para os procedimentos de sobreposição e emaranhamento, você pode testar o código até este ponto para ver a inicialização e a medição dos qubits.

Para executar o código como um programa independente, o Q# compilador no Copilot precisa saber onde iniciar o programa. Como nenhum namespace é especificado, o compilador reconhece o ponto de entrada padrão como a Main operação. Para obter mais informações, consulte Projetos e namespaces implícitos.

Seu Q# programa até este ponto agora deve ter esta aparência:

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

operation SetQubitState(desired : Result, target : Qubit) : Unit {
    if desired != M(target) {
        X(target);
    }
}

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
        
    
    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

Copie e cole o exemplo completo de código na janela de código do Copilot for Azure Quantum, ajuste o deslizador para definir o número de tiros como "1" e selecione Executar. Os resultados são exibidos no histograma e nos campos Resultados .

Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0

Como os qubits ainda não foram manipulados, eles mantiveram seus valores iniciais: o primeiro qubit retorna One toda vez e o segundo qubit retorna Zero.

Se você alterar o valor de initial para Zero e executar o programa novamente, você deve observar que o primeiro qubit também retorna Zero toda vez.

Q1 - Zeros: 1000
Q1 - Ones: 0
Q2 - Zeros: 1000
Q2 - Ones: 0

Gorjeta

Selecione Ctrl-Z ou Editar > Desfazer e salve seu arquivo sempre que introduzir uma alteração de teste no código antes de executá-lo novamente.

Coloque um qubit em superposição

Atualmente, os qubits no programa estão todos em um estado clássico, ou seja, eles são 1 ou 0. Você sabe disso porque o programa inicializa os qubits para um estado conhecido e você não adicionou nenhum processo para manipulá-los. Antes de emaranhar os qubits, você coloca o primeiro qubit em um estado de superposição, onde uma medição do qubit retorna Zero ~50% do tempo e One ~50% do tempo. Conceitualmente, o qubit pode ser pensado como tendo uma probabilidade igual de medir um Zero ou One.

Para colocar um qubit em superposição, Q# fornece a Hoperação , ou Hadamard. Lembre-se X da operação de Inicializar um qubit para um procedimento de estado conhecido anteriormente, que inverteu um qubit de 0 para 1 (ou vice-versa), a H operação inverte o qubit no meio do caminho para um estado de probabilidades iguais de Zero ou One. Quando medido, um qubit em superposição deve retornar aproximadamente um número igual de Zero e One resultados.

Modifique o Main código na operação redefinindo o valor inicial e One inserindo uma linha para a H operação:

for test in 1..count {
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        H(q1);                // Add the H operation after initialization and before measurement

        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2); 
        ...

Agora, quando você executa o programa, você pode ver os resultados do primeiro qubit em superposição.

Q1 - Zeros: 523            // results vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0

Toda vez que você executa o programa, os resultados para o primeiro qubit variam ligeiramente, mas serão próximos de 50% One e 50%, Zeroenquanto os resultados para o segundo qubit permanecem Zero o tempo todo.

Q1 - Zeros: 510           
Q1 - Ones: 490
Q2 - Zeros: 1000
Q2 - Ones: 0

Inicializar o primeiro qubit para Zero retornar resultados semelhantes.

Q1 - Zeros: 504           
Q1 - Ones: 496
Q2 - Zeros: 1000
Q2 - Ones: 0

Nota

Ao mover o controle deslizante no Copilot para Azure Quantum e aumentar o número de disparos, você pode ver como os resultados da sobreposição variam ligeiramente ao longo da distribuição dos disparos.

Emaranhar dois qubits

Como mencionado anteriormente, qubits emaranhados são conectados de tal forma que não podem ser descritos independentemente uns dos outros. Ou seja, qualquer operação que aconteça com um qubit, também acontece com o qubit emaranhado. Isso permite que você saiba o estado resultante de um qubit sem medi-lo, apenas medindo o estado do outro qubit. (Este exemplo usa dois qubits; no entanto, também é possível emaranhar três ou mais qubits).

Para permitir o emaranhamento, Q# fornece a CNOT operação, que significa Controlled-NOT. O resultado da execução desta operação em dois qubits é inverter o segundo qubit se o primeiro qubit for One.

Adicione a CNOT operação ao seu programa imediatamente após a H operação. Seu programa completo deve ter esta aparência:

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

    operation SetQubitState(desired : Result, target : Qubit) : Unit {
        if desired != M(target) {
            X(target);
        }
    }

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = Zero;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
    
        H(q1);            
        CNOT(q1, q2);      // Add the CNOT operation after the H operation

        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }

Agora, quando você executar o programa, você deve ver algo como:

Q1 - Zeros: 502           // results will vary
Q1 - Ones: 498
Q2 - Zeros: 502
Q2 - Ones: 498

Observe que as estatísticas para o primeiro qubit não mudaram (ainda há uma chance de ~50/50 de uma Zero ou uma One medição posterior), mas os resultados da medição para o segundo qubit são sempre os mesmos que a medição do primeiro qubit, não importa quantas vezes você execute o programa. A CNOT operação entrelaçou os dois qubits, de modo que o que quer que aconteça a um deles, aconteça ao outro.

Pré-requisitos

Para desenvolver e executar o exemplo de código em seu ambiente de desenvolvimento local:

Criar um novo Q# ficheiro

  1. Abra o Visual Studio Code e selecione File > New Text File para criar um novo arquivo.
  2. Guarde o ficheiro como CreateBellStates.qs. Este ficheiro irá conter o código para o Q# seu programa.

Inicializar um qubit para um estado conhecido

A primeira etapa é definir uma Q# operação que inicializa um qubit para um estado conhecido. Esta operação pode ser chamada para definir um qubit para um estado clássico, o que significa que retorna Zero 100% do tempo ou retorna One 100% do tempo. Zero e One são Q# valores que representam os dois únicos resultados possíveis de uma medição de um qubit.

Abra CreateBellStates.qs e copie o seguinte código:

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

operation SetQubitState(desired : Result, target : Qubit) : Unit {
    if desired != M(target) {
        X(target);
    }
}

O exemplo de código apresenta duas operações M padrão e X, que transformam o estado de um qubit.

A SetQubitState operação:

  1. Usa dois parâmetros: um tipo Result, chamado desired, que representa o estado desejado para o qubit estar em (Zero ou One), e um tipo Qubit.
  2. Executa uma operação de medição, M, que mede o estado do qubit (Zero ou One) e compara o resultado com o valor especificado em desired.
  3. Se a medição não corresponder ao valor comparado, ela executa uma X operação, que inverte o estado do qubit para onde as probabilidades de uma medição retornam Zero e One são invertidas. Desta forma, SetQubitState sempre coloca o qubit alvo no estado desejado.

Escrever uma operação de teste para testar o estado Bell

Em seguida, para demonstrar o efeito da SetQubitState operação, crie outra operação chamada Main. Esta operação aloca dois qubits, chama SetQubitState para definir o primeiro qubit para um estado conhecido e, em seguida, mede os qubits para ver os resultados.

Adicione a seguinte operação ao seu CreateBellStates.qs arquivo após a SetQubitState operação:

operation Main() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}

No código, as count variáveis e initial são definidas como 1000 e One respectivamente. Esta etapa inicializa o primeiro qubit e One mede cada qubit 1000 vezes.

A Mainoperação:

  1. Usa dois parâmetros: count, o número de vezes para executar uma medição e initial, o estado desejado para inicializar o qubit.
  2. Chama a use instrução para inicializar dois qubits.
  3. Loops para count iterações. Para cada loop,
    1. Chamadas SetQubitState para definir um valor especificado initial no primeiro qubit.
    2. Chama SetQubitState novamente para definir o segundo qubit para um Zero estado.
    3. Usa a M operação para medir cada qubit.
    4. Armazena o número de medidas para cada qubit que retornam One.
  4. Depois que o loop é concluído, ele chama SetQubitState novamente para redefinir os qubits para um estado conhecido (Zero) para permitir que outros aloquem os qubits em um estado conhecido. A redefinição do qubit é exigida use pela instrução.
  5. Finalmente, ele usa a Message função para imprimir uma mensagem para o console antes de retornar os resultados.

Executar o código

Antes de passar para os procedimentos de sobreposição e emaranhamento, teste o código até este ponto para ver a inicialização e medição dos qubits.

Para executar o código como um programa independente, o Q# compilador precisa saber onde iniciar o programa. Como nenhum namespace é especificado, o compilador reconhece o ponto de entrada padrão como a Main operação. Para obter mais informações, consulte Projetos e namespaces implícitos.

  1. Seu CreateBellStates.qs arquivo até este ponto agora deve ter esta aparência:

    import Microsoft.Quantum.Intrinsic.*;
    import Microsoft.Quantum.Canon.*;
    
    operation SetQubitState(desired : Result, target : Qubit) : Unit {
        if desired != M(target) {
            X(target);
        }
    }
    
    operation Main() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = One;
    
        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
    
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                numOnesQ1 += 1;
            }
            if resultQ2 == One {
                numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
    
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
    }
    
  2. Antes de executar o programa, verifique se o perfil de destino está definido como Sem restrições. Selecione Exibir -> Paleta de comandos, procure QIR, selecione Q#: Definir o perfil de destino do Azure Quantum QIR e, em seguida, selecione Q#: irrestrito.

    Nota

    Se o perfil de destino não estiver definido como Sem restrições, você receberá um erro ao executar o programa.

  3. Para executar o programa, selecione Executar arquivo na lista suspensa do ícone de reprodução no canto superior direito, selecione Q# na lista de comandos que precedem a operação ou pressione Ctrl+F5.Main O programa executa a Main operação no simulador padrão.

  4. Sua saída aparece no console de depuração.

    Q1 - Zeros: 0
    Q1 - Ones: 1000
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

    Como os qubits ainda não foram manipulados, eles mantiveram seus valores iniciais: o primeiro qubit retorna One toda vez e o segundo qubit retorna Zero.

  5. Se você alterar o valor de initial para Zero e executar o programa novamente, você deve observar que o primeiro qubit também retorna Zero toda vez.

    Q1 - Zeros: 1000
    Q1 - Ones: 0
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

Gorjeta

Selecione Ctrl-Z ou Editar > Desfazer e salve seu arquivo sempre que introduzir uma alteração de teste no código antes de executá-lo novamente.

Coloque um qubit em superposição

Atualmente, os qubits no programa estão todos em um estado clássico, ou seja, eles são 1 ou 0. Você sabe disso porque o programa inicializa os qubits para um estado conhecido e você não adicionou nenhum processo para manipulá-los. Antes de emaranhar os qubits, você coloca o primeiro qubit em um estado de superposição, onde uma medição do qubit retorna Zero 50% do tempo e One 50% do tempo. Conceitualmente, o qubit pode ser pensado como meio caminho entre o Zero e One.

Para colocar um qubit em superposição, Q# fornece a Hoperação , ou Hadamard. Lembre-se da X operação do procedimento Inicializar um qubit para um estado conhecido anteriormente, que inverteu um qubit de Zero para One (ou vice-versa), a H operação inverte o qubit no meio do caminho para um estado de probabilidades iguais de Zero ou One. Quando medido, um qubit em superposição deve retornar aproximadamente um número igual de Zero e One resultados.

  1. Modifique o código na Main operação para incluir a H operação:

    for test in 1..count {
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
    
            H(q1);                // Add the H operation after initialization and before measurement
    
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2); 
            ...
    
  2. Agora, quando você executa o programa, você pode ver os resultados do primeiro qubit em superposição:

    Q1 - Zeros: 523            // results will vary
    Q1 - Ones: 477
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  3. Toda vez que você executa o programa, os resultados para o primeiro qubit variam ligeiramente, mas serão próximos de 50% One e 50%, Zeroenquanto os resultados para o segundo qubit permanecem Zero o tempo todo.

    Q1 - Zeros: 510           
    Q1 - Ones: 490
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  4. Inicializar o primeiro qubit para Zero retornar resultados semelhantes.

    Q1 - Zeros: 504           
    Q1 - Ones: 496
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

Emaranhar dois qubits

Como mencionado anteriormente, qubits emaranhados são conectados de tal forma que não podem ser descritos independentemente uns dos outros. Ou seja, qualquer operação que aconteça com um qubit, também acontece com o qubit emaranhado. Isso permite que você saiba o estado resultante de um qubit sem medi-lo, apenas medindo o estado do outro qubit. (Este exemplo usa dois qubits; no entanto, também é possível emaranhar três ou mais qubits).

Para permitir o emaranhamento, Q# fornece a CNOT operação, que significa Controlled-NOT. O resultado da execução desta operação em dois qubits é inverter o segundo qubit se o primeiro qubit for One.

  1. Adicione a CNOT operação ao seu programa imediatamente após a H operação. Seu programa completo deve ter esta aparência:

    import Microsoft.Quantum.Intrinsic.*;
    import Microsoft.Quantum.Canon.*;
    
        operation SetQubitState(desired : Result, target : Qubit) : Unit {
            if desired != M(target) {
                X(target);
            }
        }
    
    operation Main() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = Zero;
    
        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
    
            H(q1);            
            CNOT(q1, q2);      // Add the CNOT operation after the H operation
    
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                numOnesQ1 += 1;
            }
            if resultQ2 == One {
                numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
    
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
    
        }
    
    
    Q1 - Zeros: 502           
    Q1 - Ones: 498       // results will vary
    Q2 - Zeros: 502
    Q2 - Ones: 498
    Result: "(502, 498, 502, 498)"
    

As estatísticas para o primeiro qubit não mudaram (uma chance de 50/50 de uma Zero ou uma One medição posterior), mas os resultados da medição para o segundo qubit são sempre os mesmos que a medição do primeiro qubit. A CNOT operação entrelaçou os dois qubits, de modo que o que quer que aconteça a um deles, aconteça ao outro.

Traçar o histograma de frequência

Vamos visualizar a distribuição dos resultados obtidos com a execução do programa quântico várias vezes. O histograma de frequência ajuda a visualizar a distribuição de probabilidade desses resultados.

  1. Selecione View -> Command Palette, ou pressione Ctrl+Shift+P e digite "histograma", que deve exibir a Q#opção : Executar arquivo e mostrar histograma . Você também pode selecionar Histograma na lista de comandos anteriores ao Main. Selecione esta opção para abrir a janela do Q# histograma.

  2. Insira um número de tiros para executar o programa, por exemplo, 100 tiros e pressione Enter. O histograma é exibido na janela do Q# histograma.

  3. Cada barra no histograma corresponde a um resultado possível, e sua altura representa o número de vezes que o resultado é observado. Neste caso, existem 50 resultados únicos diferentes. Note que para cada resultado os resultados da medição para o primeiro e o segundo qubit são sempre os mesmos.

    Captura de tela da janela de Q# histograma no Visual Studio Code.

    Gorjeta

    Você pode ampliar o histograma usando a roda de rolagem do mouse ou um gesto do trackpad. Quando ampliado, você pode mover o gráfico pressionando Alt durante a rolagem.

  4. Selecione uma barra para exibir a porcentagem desse resultado.

  5. Selecione o ícone de configurações no canto superior esquerdo para exibir as opções. Você pode exibir os 10 melhores resultados, os 25 melhores resultados ou todos os resultados. Você também pode classificar os resultados de alto para baixo ou baixo para alto.

    Captura de tela da janela de Q# histograma no Visual Studio Code mostrando como exibir configurações.

Explore outros Q# tutoriais:

  • O algoritmo de pesquisa de Grover mostra como escrever um Q# programa que usa o algoritmo de pesquisa de Grover.
  • Quantum Fourier Transform explora como escrever um Q# programa que aborda diretamente qubits específicos.
  • Os Quantum Katas são tutoriais individualizados e exercícios de programação destinados a ensinar os elementos da computação quântica e Q# programação ao mesmo tempo.