Tutorial: Implementar um gerador de número quântico aleatório em Q#
Observação
O Microsoft Quantum Development Kit (QDK clássico) não terá mais suporte após 30 de junho de 2024. Se você for um desenvolvedor de QDK existente, recomendamos fazer a transição para o novo QDK (QDK Moderno) do Azure Quantum Development Kit para continuar desenvolvendo soluções quânticas. Para obter mais informações, consulte Migrar seu Q# código para o QDK moderno.
Saiba como escrever um programa quântico básico no Q# que aproveita a natureza da mecânica quântica para produzir um número aleatório.
Neste tutorial, você irá:
- Crie um Q# programa.
- Examine os componentes main de um Q# programa.
- Defina a lógica de um problema.
- Combine operações clássicas e quânticas para resolver um problema.
- Trabalhar com qubits e superposição para criar um gerador quântico de números aleatórios.
Dica
Se você quiser acelerar sua jornada de computação quântica, marcar Código com o Azure Quantum, um recurso exclusivo do site do Azure Quantum. Aqui, você pode executar exemplos internos Q# ou seus próprios Q# programas, gerar um novo Q# código 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 no Azure Quantum:
- Uma conta de email da Microsoft (MSA).
Para desenvolver e executar o exemplo de código em Visual Studio Code:
A versão mais recente do Visual Studio Code ou abrir o VS Code na Web.
A versão mais recente da extensão do Azure Quantum Development Kit . Para obter detalhes de instalação, consulte Instalando o QDK moderno no VS Code.
Se você quiser usar o Jupyter Notebooks, também precisará instalar as extensões python e Jupyter e o pacote python mais recente
qsharp
. Para fazer isso, abra um terminal e execute o seguinte comando:$ pip install --upgrade qsharp
Definir o problema
Computadores clássicos não produzem números aleatórios, mas sim números pseudoaleatórios. Um gerador de números pseudoaleatórios gera uma sequência de números determinística com base em algum valor inicial, chamado de semente. Para se aproximar melhor de valores aleatórios, essa semente geralmente é a hora atual do relógio da CPU.
Os computadores quânticos, por outro lado, podem gerar números verdadeiramente aleatórios. Isso ocorre porque a medida de um qubit na superposição é um processo probabilístico. O resultado da medida é aleatório e não há como prever o resultado. Esse é o princípio básico dos geradores de número aleatório quântico.
Um qubit é uma unidade de informações quânticas que podem estar em superposição. Quando medido, um qubit só pode estar no estado 0 ou no estado 1. No entanto, antes da medida, o estado do qubit representa a probabilidade de ler 0 ou 1 com uma medida.
Você começa colocando um qubit em um estado de base, por exemplo, zero. A primeira etapa do gerador de número aleatório é usar uma operação hadamard para colocar o qubit em uma superposição igual. A medida desse estado resulta em um zero ou um com 50% de probabilidade de cada resultado, um bit verdadeiramente aleatório.
Não há como saber o que você obterá após a medida do qubit na superposição e o resultado é um valor diferente sempre que o código é invocado. Mas como você pode usar esse comportamento para gerar números aleatórios maiores?
Digamos que você repita o processo quatro vezes, gerando esta sequência de dígitos binários:
$${0, 1, 1, 0}$$
Se você concatenar ou combinar esses bits em uma cadeia de caracteres de bits, poderá formar um número maior. Neste exemplo, a sequência de bits ${0110}$ é equivalente a seis em decimal.
$${0110_{\ binary} \equiv 6_{\ decimal}}$$
Se você repetir esse processo muitas vezes, poderá combinar vários bits para formar qualquer número grande. Agora você pode fornecer ao seu superior esse número como uma senha segura, já que você pode ter certeza de que nenhum hacker espacial conseguirá determinar os resultados da sequência de medições.
Definir a lógica do gerador de números aleatórios
Vamos descrever qual deve ser a lógica de um gerador de números aleatórios, desde que tenhamos um gerador de bits aleatório:
- Defina
max
como o número máximo que você deseja gerar. - Defina o número de bits aleatórios que você precisa gerar. Isso é feito calculando de quantos bits,
nBits
, precisamos para expressar inteiros atémax
. - Gere uma cadeia de caracteres de bits aleatória com comprimento
nBits
. - Se a cadeia de caracteres de bits representar um número maior que
max
, volte para a etapa três. - Caso contrário, o processo está concluído. Retorna o número gerado como um inteiro.
Como exemplo, vamos definir max
como 12. Ou seja, 12 é o maior número que você deseja usar como senha segura.
Você precisa de ${\lfloor ln(12) / ln(2) + 1 \rfloor}$ ou quatro bits para representar um número entre 0 e 12. (Para fins de brevidade, não entraremos em detalhes sobre como derivar essa equação.)
Digamos que você gere a cadeia de caracteres de bits ${1101_{\ binary}}$, que é equivalente a ${13_{\ decimal}}$. Como 13 é maior que 12, você repete o processo.
Em seguida, você gera a cadeia de caracteres de bits ${0110_{\ binary}}$, que é equivalente a ${6_{\ decimal}}$. Já que 6 é menor que 12, o processo é concluído.
O gerador de número aleatório quântico retornará o número 6 como sua senha. Na prática, defina um número maior como o máximo, pois números menores são fáceis de decifrar, basta tentar todas as senhas possíveis. Na verdade, para aumentar a dificuldade de adivinhar ou decifrar sua senha, você pode usar o código ASCII para converter o formato binário em texto e gerar uma senha usando números, símbolos e letras maiúsculas e minúsculas.
Gravar um gerador de bits aleatório
A primeira etapa é gravar uma Q# operação que gere um bit aleatório. Essa operação será um dos blocos de construção do gerador de número aleatório.
operation GenerateRandomBit() : Result {
// Allocate a qubit.
use q = Qubit();
// Set the qubit into superposition of 0 and 1 using the Hadamard
H(q);
// At this point the qubit `q` has 50% chance of being measured in the
// |0〉 state and 50% chance of being measured in the |1〉 state.
// Measure the qubit value using the `M` operation, and store the
// measurement value in the `result` variable.
let result = M(q);
// Reset qubit to the |0〉 state.
// Qubits must be in the |0〉 state by the time they are released.
Reset(q);
// Return the result of the measurement.
return result;
}
Agora, observe o novo código.
- Você define a operação
GenerateRandomBit
, que não usa nenhuma entrada e produz um valor do tipoResult
. O tipoResult
representa o resultado de uma medida e pode ter dois valores possíveis:Zero
eOne
. - Você aloca um único qubit com o
use
palavra-chave. Quando é alocado, um qubit está sempre no estadoZero
. - Use a
H
operação para colocar o qubit em uma superposição igual. - Use a
M
operação para medir o qubit, retornar o valor medido (Zero
ouOne
). - Use a
Reset
operação para redefinir o qubit para o estado |0〉.
Ao colocar o qubit em sobreposição com a operação H
e medi-lo com a operação M
, o resultado será um valor diferente cada vez que o código for invocado.
Visualizar o Q# código com a esfera Bloch
Na esfera Bloch, o polo norte representa o valor clássico 0 e o polo sul representa o valor clássico 1. Qualquer sobreposição pode ser representada por um ponto na esfera (representada por uma seta). Quanto mais próxima a extremidade da seta estiver de um polo, maior a probabilidade de o qubit recolher o valor clássico atribuído a esse polo quando medido. Por exemplo, o estado do qubit representado pela seta na figura abaixo terá uma probabilidade mais alta de dar o valor 0 se medirmos isso.
Podemos usar essa representação para visualizar o que o código está fazendo:
Primeiro, começamos com um qubit inicializado no estado 0 e aplicamos uma operação
H
para criar uma sobreposição igual na qual as probabilidades de 0 e 1 são as mesmas.Em seguida, medimos o qubit e salvamos a saída:
Como o resultado da medida é aleatório e as probabilidades de medir 0 e 1 são as mesmas, você obteve um bit completamente aleatório. Podemos chamar essa operação várias vezes para criar inteiros. Por exemplo, se chamar a operação três vezes para obter três bits aleatórios, você poderá criar números aleatórios de 3 bits (ou seja, um número aleatório entre 0 e 7).
Gravar um gerador de número aleatório completo
Primeiro, você precisa adicionar os namespaces necessários Q# ao programa. Para o gerador de número aleatório completo, você precisa incluir três Q# namespaces:
Microsoft.Quantum.Math
,Microsoft.Quantum.Intrinsic
eMicrosoft.Quantum.Convert
.open Microsoft.Quantum.Convert; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Math;
Em seguida, você define a
GenerateRandomNumberInRange
operação. Essa operação chama repetidamente a operaçãoGenerateRandomBit
para criar uma cadeia de caracteres de bits./// Generates a random number between 0 and `max`. operation GenerateRandomNumberInRange(max : Int) : Int { // Determine the number of bits needed to represent `max` and store it // in the `nBits` variable. Then generate `nBits` random bits which will // represent the generated random number. mutable bits = []; let nBits = BitSizeI(max); for idxBit in 1..nBits { set bits += [GenerateRandomBit()]; } let sample = ResultArrayAsInt(bits); // Return random number if it is within the requested range. // Generate it again if it is outside the range. return sample > max ? GenerateRandomNumberInRange(max) | sample; }
Vamos dedicar um momento para analisar o novo código.
- Você precisa calcular o número de bits necessários para expressar inteiros até
max
. ABitSizeI
função doMicrosoft.Quantum.Math
namespace converte um inteiro no número de bits necessários para representá-lo. - A operação
SampleRandomNumberInRange
usa um loopfor
para gerar números aleatórios até que ele gere um igual a ou menor quemax
. Ofor
loop funciona exatamente da mesma forma que umfor
loop em outras linguagens de programação. - A variável
bits
é uma variável mutável. Uma variável mutável é aquela que pode ser alterada durante a computação. Você usa a diretivaset
para alterar o valor de uma variável mutável. - A
ResultArrayAsInt
função vem doMicrosoft.Quantum.Convert
namespace. Essa função converte a cadeia de caracteres de bits em um inteiro positivo.
- Você precisa calcular o número de bits necessários para expressar inteiros até
Por fim, você adiciona um ponto de entrada. Neste exemplo, a
Main
operação é o ponto de entrada do programa. Ele chama aGenerateRandomNumberInRange
operação para gerar um número aleatório entre 0 e 100.@EntryPoint() operation Main() : Int { let max = 100; Message($"Sampling a random number between 0 and {max}: "); // Generate random number in the 0..max range. return GenerateRandomNumberInRange(max); }
A diretiva
let
declara variáveis que não são alteradas durante a computação. Aqui, definimos o valor máximo como 100.O código completo para o gerador de número aleatório é o seguinte:
namespace QuantumRandomNumberGenerator {
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Math;
@EntryPoint()
operation Main() : Int {
let max = 100;
Message($"Sampling a random number between 0 and {max}: ");
// Generate random number in the 0..max range.
return GenerateRandomNumberInRange(max);
}
/// Generates a random number between 0 and `max`.
operation GenerateRandomNumberInRange(max : Int) : Int {
// Determine the number of bits needed to represent `max` and store it
// in the `nBits` variable. Then generate `nBits` random bits which will
// represent the generated random number.
mutable bits = [];
let nBits = BitSizeI(max);
for idxBit in 1..nBits {
set bits += [GenerateRandomBit()];
}
let sample = ResultArrayAsInt(bits);
// Return random number if it is within the requested range.
// Generate it again if it is outside the range.
return sample > max ? GenerateRandomNumberInRange(max) | sample;
}
operation GenerateRandomBit() : Result {
// Allocate a qubit.
use q = Qubit();
// Set the qubit into superposition of 0 and 1 using the Hadamard
H(q);
// At this point the qubit `q` has 50% chance of being measured in the
// |0〉 state and 50% chance of being measured in the |1〉 state.
// Measure the qubit value using the `M` operation, and store the
// measurement value in the `result` variable.
let result = M(q);
// Reset qubit to the |0〉 state.
// Qubits must be in the |0〉 state by the time they are released.
Reset(q);
// Return the result of the measurement.
return result;
}
}
Executar o programa gerador de números aleatórios
Você pode executar o programa no Copilot no Azure Quantum e em Visual Studio Code como um aplicativo autônomo Q# ou usando um programa host python.
Você pode testar seu Q# código com o Copilot no Azure Quantum gratuitamente – tudo o que você precisa é de uma conta de email da Microsoft (MSA). Para obter mais informações sobre o Copilot no Azure Quantum, consulte Explorar o Azure Quantum.
Abra o Copilot no Azure Quantum em seu navegador.
Copie e cole o código a seguir no editor de código.
namespace Tutorial { open Microsoft.Quantum.Convert; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Math; @EntryPoint() operation Main() : Int { let max = 100; Message($"Sampling a random number between 0 and {max}: "); // Generate random number in the 0..max range. return GenerateRandomNumberInRange(max); } /// # Summary /// Generates a random number between 0 and `max`. operation GenerateRandomNumberInRange(max : Int) : Int { // Determine the number of bits needed to represent `max` and store it // in the `nBits` variable. Then generate `nBits` random bits which will // represent the generated random number. mutable bits = []; let nBits = BitSizeI(max); for idxBit in 1..nBits { set bits += [GenerateRandomBit()]; } let sample = ResultArrayAsInt(bits); // Return random number if it is within the requested range. // Generate it again if it is outside the range. return sample > max ? GenerateRandomNumberInRange(max) | sample; } /// # Summary /// Generates a random bit. operation GenerateRandomBit() : Result { // Allocate a qubit. use q = Qubit(); // Set the qubit into superposition of 0 and 1 using the Hadamard // operation `H`. H(q); // At this point the qubit `q` has 50% chance of being measured in the // |0〉 state and 50% chance of being measured in the |1〉 state. // Measure the qubit value using the `M` operation, and store the // measurement value in the `result` variable. let result = M(q); // Reset qubit to the |0〉 state. // Qubits must be in the |0〉 state by the time they are released. Reset(q); // Return the result of the measurement. return result; // Note that Qubit `q` is automatically released at the end of the block. } }
Selecione o número de capturas a serem executadas e clique em Executar.
Os resultados são exibidos no histograma e nos campos Resultados .
Clique em Explicar código para solicitar que o Copilot explique o código para você.
Dica
No Copilot no Azure Quantum, você pode abrir seu programa no VS Code para a Web clicando no botão do logotipo do VS Code no canto direito do editor de código.
Observação
Esse snippet de código não é executado atualmente em nenhum hardware targetsdo Azure Quantum disponível, pois o callable ResultArrayAsInt
requer uma QPU com perfil de computação completo.
Próximas etapas
Explore outros tutoriais Q#:
- O emaranhamento quântico mostra como escrever um Q# programa que manipula e mede qubits e demonstra os efeitos da superposição e do emaranhamento.
- O algoritmo de pesquisa de Grover mostra como escrever um Q# programa que usa o algoritmo de pesquisa de Grover.
- O Quantum Fourier Transforms explora como escrever um Q# programa que aborda diretamente qubits específicos.
- As Katas Quânticas são tutoriais e exercícios de programação com o objetivo de ensinar os elementos da computação quântica e Q# da programação ao mesmo tempo.
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: ao longo de 2024, vamos eliminar problemas do GitHub como o mecanismo de comentários para conteúdo e substituí-lo por um novo sistema de comentários. Para obter mais informações, consulte:Enviar e exibir comentários de