Compartilhar via


Tutorial: explorar o emaranhamento quântico com o Q#

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

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

  • Quando os bits clássicos contêm apenas um valor binário, como 0 ou 1, o estado de um qubit pode estar em uma sobreposiçã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 altera o estado do qubit fora da superposição.
  • Vários qubits podem ser emaranhados de forma que não possam ser descritos independentemente uns dos outros. Ou seja, o que acontecerá com um qubit em um par emaranhado também acontecerá com o outro qubit.

Neste tutorial, você aprenderá como:

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

Dica

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 exemplos integrados 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 para a 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 Explorar o Azure Quantum.

Inicializar um qubit para um estado conhecido

A primeira etapa é definir uma operação Q# que inicializa um qubit para um estado conhecido. Essa operação pode ser chamada para definir um qubit como um estado clássico, o que significa que, quando medida, ela 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ódigos. Não clique em Executar ainda; você executará o código posteriormente 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 introduz duas operações padrão, M e X, que transformam o estado de um qubit.

A operação SetQubitState:

  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, ele executa uma operação X, que inverte o estado do qubit para onde as probabilidades de uma medição retornar Zero e One são invertidas. Dessa forma, o SetQubitState sempre coloca o destino qubit no estado desejado.

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

Em seguida, para demonstrar o efeito da operação SetQubitState, crie outra operação chamada Main. Essa operação 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 {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set 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 para One e mede cada qubit 1.000 vezes.

A Mainoperação:

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

Executar 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 autônomo, o Q# compilador no Copilot precisa saber por 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 ficar assim:

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 {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set 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 de código completo na janela de código do Copilot para Azure Quantum , defina o slide para o número de capturas como "1" e clique em 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 todas as vezes e o segundo qubit retorna Zero.

Se você alterar o valor de initial to Zero e executar o programa novamente, observe que o primeiro qubit também retorna Zero todas as vezes.

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

Dica

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.

Colocar um qubit em sobreposição

Atualmente, os qubits no programa estão todos em um estado clássico, ou seja, 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, em que uma medida 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 ou Zero One.

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

Modifique o Main código na operação redefinindo o valor inicial para One e 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, ao executar 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 um pouco, mas estarão próximos de 50% One e 50% Zero, enquanto 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 retorna resultados semelhantes.

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

Observação

Movendo o controle deslizante no Copilot para Azure Quantum e aumentando o número de fotos, você pode ver como os resultados de superposição variam ligeiramente na distribuição das fotos.

Emaranhar dois qubits

Como mencionado anteriormente, os qubits emaranhados são conectados de modo que não podem ser descritos independentemente um do outro. Ou seja, a operação que for executada com um qubit, também será executada com os qubits emaranhados. Isso permite que você conheça o estado resultante de um qubit sem medi-lo, apenas medindo o estado de outro qubit. (Este exemplo usa dois qubits. No entanto, também é possível emaranhar três ou mais qubits).

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

Adicione a operação CNOT ao programa imediatamente após a operação H. O 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 {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set 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, ao 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 do primeiro qubit não foram alteradas (ainda há uma chance de ~50/50 de a Zero ou uma One pós-medição), 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 operação CNOT entrelaçou os dois qubits, de modo que o que acontecer com um deles acontecerá com o outro.

Pré-requisitos

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

Criar um novo Q# arquivo

  1. Abra o Visual Studio Code e selecione Arquivo > Novo Arquivo de Texto para criar um arquivo.
  2. Salve o arquivo como CreateBellStates.qs. Este arquivo conterá o código do Q# seu programa.

Inicializar um qubit para um estado conhecido

A primeira etapa é definir uma operação Q# que inicializa um qubit para um estado conhecido. Essa operação pode ser chamada para definir um qubit como um estado clássico, o que significa que ele retorna Zero 100% do tempo ou retorna One 100% do tempo. Zero e One são valores Q# que representam os únicos dois possíveis resultados 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 introduz duas operações padrão, M e X, que transformam o estado de um qubit.

A operação SetQubitState:

  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, ele executa uma operação X, que inverte o estado do qubit para onde as probabilidades de uma medição retornar Zero e One são invertidas. Dessa forma, o SetQubitState sempre coloca o destino qubit no estado desejado.

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

Em seguida, para demonstrar o efeito da operação SetQubitState, crie outra operação chamada Main. Essa 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 arquivo CreateBellStates.qs, após a operação SetQubitState:

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 {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set 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 instrução use para inicializar dois qubits.
  3. Executa loops para iterações count. Para cada loop, ela
    1. Chama SetQubitState para definir um valor initial especificado no primeiro qubit.
    2. Chama SetQubitState novamente para definir o segundo qubit como um estado Zero.
    3. Usa a operação M para medir cada qubit.
    4. Armazena o número de medições para cada qubit que retorna One.
  4. Depois que o loop for concluído, ele chamará SetQubitState novamente para redefinir os qubits para um estado conhecido (Zero) para permitir que outras pessoas aloquem os qubits em um estado conhecido. A redefinição do qubit é exigida use pela instrução.
  5. Por fim, ela usa a função Message para exibir 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é esse ponto para ver a inicialização e a medição dos qubits.

Para executar o código como um programa autônomo, o Q# compilador precisa saber por 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 ficar assim:

    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 {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set 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, certifique-se de que o perfil de destino esteja definido como Irrestrito. Selecione Exibir –> Paleta de Comandos, pesquise QIR, selecioneQ#: Defina o perfil de destino QIR do Azure Quantum e selecioneQ#: irrestrito.

    Observação

    Se o perfil de destino não estiver definido como Irrestrito, você receberá um erro ao executar o programa.

  3. Para executar o programa, selecione Executar arquivo no menu suspenso do ícone de reprodução no canto superior direito, selecione Executar na lista de comandos que precedem a Main operação ou pressione Ctrl+F5. Q# 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 todas as vezes e o segundo qubit retorna Zero.

  5. Se você alterar o valor de initial to Zero e executar o programa novamente, observe que o primeiro qubit também retorna Zero todas as vezes.

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

Dica

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.

Colocar um qubit em sobreposição

Atualmente, os qubits no programa estão todos em um estado clássico, ou seja, 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, em que uma medição do qubit retorna Zero 50% do tempo e One 50% do tempo. Conceitualmente, o qubit pode ser pensado como a metade entre o Zero e o One.

Para colocar um qubit em sobreposição, Q# fornece H, ou a operação Hadamard. Lembre-se X da 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 na metade para um estado de probabilidades iguais de Zero ou One. Quando medido, um qubit na sobreposição deve retornar aproximadamente um número igual de resultados Zero e One.

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

    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ê executar o programa, poderá ver os resultados do primeiro qubit em sobreposiçã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 um pouco, mas estarão próximos de 50% One e 50% Zero, enquanto 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 retorna resultados semelhantes.

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

Emaranhar dois qubits

Como mencionado anteriormente, os qubits emaranhados são conectados de modo que não podem ser descritos independentemente um do outro. Ou seja, a operação que for executada com um qubit, também será executada com os qubits emaranhados. Isso permite que você conheça o estado resultante de um qubit sem medi-lo, apenas medindo o estado de outro qubit. (Este exemplo usa dois qubits. No entanto, também é possível emaranhar três ou mais qubits).

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

  1. Adicione a operação CNOT ao programa imediatamente após a operação H. O 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 {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set 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 foram alteradas (uma chance de 50/50 de um Zero ou um One após a medida), mas os resultados da medida para o segundo qubit são sempre os mesmos que a medida do primeiro qubit. A CNOT operação emaranhava os dois qubits, de modo que o que quer que acontecesse com um deles, acontecesse com o outro.

Plotar 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 Exibir -> Paleta de Comandos ou pressione Ctrl+Shift+P e digite "histograma", que deve abrir a opção : Executar arquivo e mostrar histogramaQ#. Você também pode selecionar Histograma na lista de comandos anteriores Main. Selecione essa opção para abrir a janela do histograma Q# .

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

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

    Faça uma captura de tela da janela do Q# histograma no Visual Studio Code.

    Dica

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

  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 principais resultados, os 25 principais resultados ou todos os resultados. Você também pode classificar os resultados de alto para baixo ou de baixo para alto.

    Faça uma captura de tela da janela do Q# histograma no Visual Studio Code mostrando como exibir as configurações.

Explore outros tutoriais Q#:

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