Tutorial: Explorar o entrelaçamento quântico com Q#

Este tutorial mostra-lhe como escrever um Q# programa que manipula e mede qubits e demonstra os efeitos da sobreposição e do entrelaçamento. Prepara dois qubits num estado quântico específico, aprende a operar em qubits com Q# para alterar o respetivo estado e demonstra os efeitos da sobreposição e do entrelaçamento. Vai criar o seu Q# programa peça a peça para introduzir estados, operações e medidas de qubit.

Nota

O Microsoft Quantum Development Kit (QDK Clássico) deixará de ser suportado após 30 de junho de 2024. Se for um programador de QDK existente, recomendamos que faça a transição para o novo Azure Quantum Development Kit (QDK Moderno) para continuar a desenvolver soluções quânticas. Para obter mais informações, veja Migrar o código Q# para o QDK Moderno.

Seguem-se alguns conceitos fundamentais a compreender antes de começar:

  • Quando os bits clássicos contêm um único valor binário, como 0 ou 1, o estado de um qubit pode estar numa 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 da sobreposição.
  • Vários qubits podem ser entrelaçados de modo a que não possam ser descritos de forma independente uns dos outros. Ou seja, o que quer que aconteça a um qubit num par entrelaçado também acontece com o outro qubit.

Neste tutorial, irá aprender a:

  • Q# Create operações para inicializar um qubit para um estado pretendido.
  • Coloque um qubit na sobreposição.
  • Entrelaçar um par de qubits.
  • Meça um qubit e observe os resultados.

Dica

Se quiser acelerar o seu percurso de computação quântica, consulte Código com o Azure Quantum, uma funcionalidade exclusiva do site do Azure Quantum. Aqui, pode executar exemplos incorporados Q# ou os seus próprios Q# programas, gerar novo Q# código a partir das suas instruções, abrir e executar o código no VS Code para a Web com um clique e fazer perguntas sobre computação quântica ao Copilot.

Pré-requisitos

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

  • Uma conta de e-mail da Microsoft (MSA).

Para obter mais informações sobre o Copilot, veja Explorar o Azure Quantum.

Inicializar um qubit para um estado conhecido

O primeiro passo é definir uma Q# operação que irá inicializar um qubit para um estado conhecido. Isto pode ser chamado para definir um qubit para um estado clássico, o que significa que, quando medido, devolve Zero 100% do tempo ou devolve One 100% do tempo. Medir um qubit devolve um Q# tipo Result, que só pode ter um valor de Zero ou One.

Abra o Copilot do Azure Quantum e copie o seguinte código para a janela do editor de código. Não clique em Executar ainda; Irá executar o código mais tarde no tutorial.

   namespace Bell {
       open Microsoft.Quantum.Intrinsic;
       open 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 e MX, que transformam o estado de um qubit.

A SetQubitState operação:

  1. Utiliza dois parâmetros: um tipo Result, com o nome desired, que representa o estado pretendido para o qubit estar em (Zero ou One) e um tipo Qubit.
  2. Executa uma operação de medição, , Mque 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, executa uma X operação, que inverte o estado do qubit para onde as probabilidades de uma medição são devolvidas Zero e One são invertidas. Desta forma, SetQubitState coloca sempre o qubit de destino no estado pretendido.

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

Em seguida, para demonstrar o efeito da operação, crie outra operação com o SetQubitState nome TestBellState. 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 seguinte código para a janela do editor de código, por baixo da SetQubitState operação.

operation TestBellState() : (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 estão definidas como 1000 e One respetivamente. Isto inicializa o primeiro qubit para One e mede cada qubit 1000 vezes.

A TestBellStateoperação:

  1. Define variáveis para o contador e o estado do qubit inicial.
  2. Chama a use instrução para inicializar dois qubits.
  3. Ciclos para count iterações. Para cada ciclo,
    1. Chamadas SetQubitState para definir um valor especificado initial no primeiro qubit.
    2. Chamadas SetQubitState novamente para definir o segundo qubit como um Zero estado.
    3. Utiliza a M operação para medir cada qubit.
    4. Armazena o número de medidas para cada qubit que devolve One.
  4. Após a conclusão do ciclo, chama SetQubitState novamente para repor os qubits para um estado conhecido (Zero) para permitir que outras pessoas aloquem os qubits num estado conhecido. Esta operação é exigida pela instrução use.
  5. Por fim, utiliza a Message função para imprimir resultados nas janelas de saída do Copilot antes de devolver os resultados.

Executar o código no Copilot para o Azure Quantum

Antes de avançar para os procedimentos de sobreposição e entrelaçamento, 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 tem de saber por onde iniciar o programa. Isto é feito no Q# ficheiro ao adicionar um @EntryPoint() diretamente anterior à operação que pretende executar primeiro. Por exemplo, neste caso, é a TestBellState operação.

Nota

@EntryPoint() só é necessário para programas autónomos Q# . Ao executar um Q# programa no Jupyter Notebooks ou ao chamar um Q# programa a partir de um ficheiro anfitrião Python, não é necessário e emitirá um erro se estiver incluído.

Adicione o imediatamente antes TestBellState da @EntryPoint() operação e o programa Q# até este ponto deverá ter o seguinte aspeto:

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

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

    @EntryPoint()
    operation TestBellState() : (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 Copilot para o código do Azure Quantum , defina o diapositivo para o número de capturas como "1" e clique em Executar. Os resultados são apresentados no histograma e nos campos Resultados .

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

Uma vez que os qubits ainda não foram manipulados, mantiveram os respetivos valores iniciais: o primeiro qubit é devolvido One sempre e o segundo qubit devolve Zero.

Se alterar o valor de initial para Zero e executar o programa novamente, deve observar que o primeiro qubit também devolve Zero sempre.

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

Colocar um qubit na sobreposição

Atualmente, os qubits no programa estão todos num estado clássico, ou seja, são 1 ou 0. Sabe disso porque o programa inicializa os qubits para um estado conhecido e não adicionou nenhum processo para os manipular. Antes de entrelaçar os qubits, colocará o primeiro qubit num estado de sobreposição, onde uma medição do qubit devolverá Zero ~50% do tempo e One ~50% do tempo. Conceptualmente, o qubit pode ser considerado como tendo uma probabilidade igual de medir ou ZeroOne.

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

Modifique o código na TestBellState operação ao repor o valor inicial para One e inserir 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 executar o programa, pode ver os resultados do primeiro qubit na sobreposição.

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

Sempre que executar o programa, os resultados do primeiro qubit variam ligeiramente, mas serão próximos de 50% One e 50%, Zeroenquanto os resultados do segundo qubit permanecerão Zero sempre.

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

Inicializar o primeiro qubit para Zero devolver resultados semelhantes.

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

Nota

Ao mover o controlo de deslize no Copilot para o Azure Quantum e ao aumentar o número de capturas, pode ver como os resultados da sobreposição variam ligeiramente em relação à distribuição das capturas.

Entrelaçar dois qubits

Conforme mencionado anteriormente, os qubits entrelaçados estão ligados de modo a que não possam ser descritos de forma independente uns dos outros. Ou seja, qualquer que seja a operação que aconteça a um qubit, também acontece ao qubit entrelaçado. Isto permite-lhe saber o estado resultante de um qubit sem o medir, apenas ao medir o estado do outro qubit. (Este exemplo utiliza dois qubits; no entanto, também é possível entrelaçar três ou mais qubits).

Para ativar o entrelaçamento, 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 programa imediatamente após a H operação. O programa completo deverá ter o seguinte aspeto:

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

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

    @EntryPoint()
    operation TestBellState() : (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, quando executar o programa, deverá ver algo como:

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

Tenha em atenção que as estatísticas do primeiro qubit não foram alteradas (ainda existe uma probabilidade de ~50/50 de uma Zero medição ou posterior One ), mas os resultados da medição do segundo qubit são sempre iguais à medição do primeiro qubit, independentemente do número de vezes que executar o programa. A CNOT operação entrelaçou os dois qubits, para que o que quer que aconteça a um deles, aconteça com o outro.

Pré-requisitos

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

Create um novo Q# ficheiro

  1. Abra o Visual Studio Code e selecione Ficheiro > Novo Ficheiro de Texto para criar um novo ficheiro.
  2. Guarde o ficheiro como CreateBellStates.qs. Este ficheiro irá conter o Q# código do seu programa.

Inicializar um qubit para um estado conhecido

O primeiro passo é definir uma Q# operação que irá inicializar um qubit para um estado conhecido. Isto pode ser chamado para definir um qubit para um estado clássico, o que significa que devolve Zero 100% do tempo ou devolve One 100% do tempo. Zero e One são Q# valores que representam os únicos dois resultados possíveis de uma medição de um qubit.

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

   namespace Bell {
       open Microsoft.Quantum.Intrinsic;
       open 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 e MX, que transformam o estado de um qubit.

A SetQubitState operação:

  1. Utiliza dois parâmetros: um tipo Result, com o nome desired, que representa o estado pretendido para o qubit estar em (Zero ou One) e um tipo Qubit.
  2. Executa uma operação de medição, , Mque 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, executa uma X operação, que inverte o estado do qubit para onde as probabilidades de uma medição são devolvidas Zero e One são invertidas. Desta forma, SetQubitState coloca sempre o qubit de destino no estado pretendido.

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

Em seguida, para demonstrar o efeito da operação, crie outra operação com o SetQubitState nome TestBellState. 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.

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

operation TestBellState() : (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 estão definidas como 1000 e One respetivamente. Isto inicializa o primeiro qubit para One e mede cada qubit 1000 vezes.

A TestBellStateoperação:

  1. Utiliza dois parâmetros: count, o número de vezes para executar uma medição e initial, o estado pretendido para inicializar o qubit.
  2. Chama a use instrução para inicializar dois qubits.
  3. Ciclos para count iterações. Para cada ciclo,
    1. Chamadas SetQubitState para definir um valor especificado initial no primeiro qubit.
    2. Chamadas SetQubitState novamente para definir o segundo qubit como um Zero estado.
    3. Utiliza a M operação para medir cada qubit.
    4. Armazena o número de medidas para cada qubit que devolve One.
  4. Após a conclusão do ciclo, chama SetQubitState novamente para repor os qubits para um estado conhecido (Zero) para permitir que outras pessoas aloquem os qubits num estado conhecido. Esta operação é exigida pela instrução use.
  5. Por fim, utiliza a Message função para imprimir uma mensagem na consola antes de devolver os resultados.

Executar o código

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

Isto é feito no Q# ficheiro ao adicionar um @EntryPoint() diretamente anterior à operação que pretende executar. Por exemplo, neste caso, é a TestBellState operação.

Nota

@EntryPoint() só é necessário para programas autónomos Q# . Ao executar um Q# programa no Jupyter Notebooks ou ao chamar um Q# programa a partir de um ficheiro anfitrião Python, não é necessário e emitirá um erro se estiver incluído.

  1. O seu CreateBellStates.qs ficheiro deverá ter o seguinte aspeto:

    namespace Bell {
        open Microsoft.Quantum.Intrinsic;
        open Microsoft.Quantum.Canon;
    
           operation SetQubitState(desired : Result, target : Qubit) : Unit {
               if desired != M(target) {
                   X(target);
               }
           }
    
        @EntryPoint()
        operation TestBellState() : (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, tem de definir o perfil de destino como Sem Restrições. Selecione Ver -> Paleta de Comandos, procure QIR, selecione Q#: Defina o perfil de destino QIR do Azure Quantum e, em seguida, selecione Q#: sem restrições.

    Nota

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

  3. Para executar o programa, selecione Executar Q# Ficheiro no menu pendente ícone de reprodução no canto superior direito, clique em Executar a partir da lista de comandos abaixo @EntryPoint()ou prima Ctrl+F5. O programa executa a operação ou função marcada com o @EntryPoint() atributo no simulador predefinido.

  4. O resultado é apresentado na consola de depuração.

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

    Uma vez que os qubits ainda não foram manipulados, mantiveram os respetivos valores iniciais: o primeiro qubit é devolvido One sempre e o segundo qubit devolve Zero.

  5. Se alterar o valor de initial para Zero e executar o programa novamente, deve observar que o primeiro qubit também devolve Zero sempre.

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

Dica

Lembre-se de guardar o seu ficheiro sempre que introduzir uma alteração ao código antes de o executar novamente.

Colocar um qubit na sobreposição

Atualmente, os qubits no programa estão todos num estado clássico, ou seja, são 1 ou 0. Sabe disso porque o programa inicializa os qubits para um estado conhecido e não adicionou nenhum processo para os manipular. Antes de entrelaçar os qubits, colocará o primeiro qubit num estado de sobreposição, onde uma medição do qubit devolverá Zero 50% do tempo e One 50% do tempo. Conceptualmente, o qubit pode ser considerado a meio caminho entre o e Oneo Zero .

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

  1. Modifique o código na TestBellState 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 executar o programa, pode ver os resultados do primeiro qubit na sobreposição:

    Q1 - Zeros: 523            // results will vary
    Q1 - Ones: 477
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  3. Sempre que executar o programa, os resultados do primeiro qubit variam ligeiramente, mas serão próximos de 50% One e 50%, Zeroenquanto os resultados do segundo qubit permanecerão Zero sempre.

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

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

Entrelaçar dois qubits

Conforme mencionado anteriormente, os qubits entrelaçados estão ligados de modo a que não possam ser descritos de forma independente uns dos outros. Ou seja, qualquer que seja a operação que aconteça a um qubit, também acontece ao qubit entrelaçado. Isto permite-lhe saber o estado resultante de um qubit sem o medir, apenas ao medir o estado do outro qubit. (Este exemplo utiliza dois qubits; no entanto, também é possível entrelaçar três ou mais qubits).

Para ativar o entrelaçamento, 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 programa imediatamente após a H operação. O programa completo deverá ter o seguinte aspeto:

    namespace Bell {
        open Microsoft.Quantum.Intrinsic;
        open Microsoft.Quantum.Canon;
    
           operation SetQubitState(desired : Result, target : Qubit) : Unit {
               if desired != M(target) {
                   X(target);
               }
           }
    
        @EntryPoint()
        operation TestBellState() : (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);
    
                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
    

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

Desenhar o histograma de frequência

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

  1. Selecione Ver -> Paleta de Comandos ou prima Ctrl+Shift+P e escreva "histograma", que deverá apresentar a opção Q#: Executar ficheiro e mostrar histograma . Também pode clicar em Histograma a partir da lista de comandos abaixo @EntryPoint(). Selecione esta opção para abrir a janela do Q# histograma.

  2. Introduza uma série de imagens para executar o programa, por exemplo, 100 tiros e prima Enter. O histograma será apresentado na janela do Q# histograma.

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

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

    Dica

    Pode ampliar o histograma com a roda do rato ou um gesto de trackpad. Quando ampliado, pode deslocar o gráfico ao premir "Alt" durante o deslocamento.

  4. Clique numa barra para apresentar a percentagem desse resultado.

  5. Clique no ícone de definições no canto superior esquerdo para apresentar as opções. Pode apresentar os 10 melhores resultados, os 25 melhores resultados ou todos os resultados. Também pode ordenar os resultados de alto a baixo ou baixo para alto.

    Captura de ecrã da janela histograma Q# no Visual Studio Code a mostrar como apresentar as definições.

Passos seguintes

Explore outros Q# tutoriais: