Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Neste tutorial, aprende a escrever um programa quântico básico em Q# que tira partido da natureza da mecânica quântica para produzir um número aleatório.
Neste tutorial, irá:
- Crie um programa Q#.
- Analise os principais componentes 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 sobreposição para criar um gerador quântico de números aleatórios.
Gorjeta
Se você quiser acelerar sua jornada de computação quântica, confira Code with Azure Quantum, um recurso exclusivo do site Microsoft Quantum. Aqui, pode executar exemplos incorporados Q# ou os seus próprios Q# programas, gerar novo Q# código a partir dos seus prompts, abrir e executar o seu código no VS Code for the Web com apenas um clique e fazer ao Copilot perguntas sobre computação quântica.
Pré-requisitos
Para executar o exemplo de código no Copilot no Azure Quantum, deve ter uma conta de email Microsoft (MSA).
Para desenvolver e executar o exemplo de código no Visual Studio Code (VS Code) e no Jupyter Notebook, instale o seguinte:
A versão mais recente do VS Code ou abrir o VS Code para a Web.
A versão mais recente da extensão Azure Quantum Development Kit (QDK). Para obter detalhes da instalação, consulte Configurar a extensão QDK.
A mais recente
qdkbiblioteca Python com ojupyterextra. Para instalar estes, abra um terminal e execute o seguinte comando:pip install --upgrade "qdk[jupyter]"
Definir o problema
Os 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 determinística de números com base em algum valor inicial, chamado de semente. Para melhor aproximar os valores aleatórios, esta semente é frequentemente 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 medição de um qubit em superposição é um processo probabilístico. O resultado da medição é aleatório e não há como prever o resultado. Este é o princípio básico dos geradores quânticos de números aleatórios.
Um qubit é uma unidade de informação quântica que pode estar em sobreposição. Quando medido, um qubit só pode estar no estado 0 ou no estado 1. No entanto, antes da medição, o estado do qubit representa a probabilidade de ler um 0 ou um 1 com uma medição.
Você começa tomando um qubit em um estado base, por exemplo, zero. O primeiro passo do gerador de números aleatórios é usar uma operação Hadamard para colocar o qubit em uma superposição igual. A medição deste 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 medição do qubit em superposição, e o resultado é um valor diferente cada vez que o código é invocado. Mas como você pode usar esse comportamento para gerar números aleatórios maiores?
Digamos que repete o processo quatro vezes e gera esta sequência de dígitos binários:
$${0, 1, 1, 0}$$
Se concatenar, ou combinar, estes bits numa cadeia de bits, pode formar um número maior. Neste exemplo, a sequência de bits ${0110}$ é equivalente a seis em decimal.
$${0110_{\ binário} \equiv 6_{\ decimal}}$$
Se você repetir esse processo muitas vezes, poderá combinar vários bits para formar qualquer número grande. Usando este método, você pode criar um número para usar como uma senha segura, uma vez que você pode ter certeza de que nenhum hacker poderia 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:
- Defina
maxcomo o número máximo que você deseja gerar. - Defina o número de bits aleatórios que você precisa gerar. Isso é feito calculando quantos bits,
nBits, são necessários para expressar inteiros atémax. - Gere uma cadeia de bits aleatórios que tenha
nBitsde comprimento. - Se a cadeia de bits representar um número maior do que
max, volte ao passo três. - De outro modo, o processo está concluído. Devolva o número gerado como um número inteiro.
Como exemplo, vamos definir max para 12. Ou seja, 12 é o maior número que você deseja usar como senha.
Você precisa de ${\lfloor ln(12) / ln(2) + 1 \rfloor}$, ou 4 bits para representar um número entre 0 e 12. Podemos usar a função incorporada BitSizeI, que aceita qualquer número inteiro e retorna o número de bits necessários para representá-lo.
Digamos que gera a cadeia de bits ${1101_{\ binary}}$, que equivale a ${13_{\ decimal}}$. Uma vez que 13 é maior que 12, repete-se o processo.
Em seguida, gera a cadeia de bits ${0110_{\ binary}}$, que equivale a ${6_{\ decimal}}$. Uma vez que 6 é menor que 12, o processo está concluído.
O gerador de números aleatórios quânticos retornará o número 6 como sua senha. Na prática, defina um número maior como o máximo, porque números mais baixos são fáceis de decifrar apenas tentando todas as senhas possíveis. Na verdade, para aumentar a dificuldade de adivinhar ou quebrar sua senha, você pode usar o código ASCII para converter binário em texto e gerar uma senha usando números, símbolos e letras maiúsculas e minúsculas.
Escreva um gerador de bits aleatório
O primeiro passo é escrever uma Q# operação que gere um bit aleatório. Esta operação será um dos blocos de construção do gerador de números aleatórios.
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 dê uma olhada no novo código.
- Você define a
GenerateRandomBitoperação, que não recebe nenhuma entrada e produz um valor do tipoResult. OResulttipo representa o resultado de uma medição e pode ter dois valores possíveis:ZeroouOne. - Você aloca um único qubit com a
usepalavra-chave. Quando é alocado, um qubit está sempre no estado |0〉. - Você usa a
Hoperação para colocar o qubit em uma superposição igual. - Você usa a
Moperação para medir o qubit, retornar o valor medido (ZeroouOne). - Use a
Resetoperação para redefinir o qubit para o estado |0〉.
Ao colocar o qubit em sobreposição com a H operação e medi-lo com a M operação, o resultado é um valor diferente cada vez que o código é invocado.
Visualize o Q# código com a esfera de Bloch
Na esfera de 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 estiver a ponta da seta de um polo, maior a probabilidade de o qubit colapsar para o valor clássico atribuído a esse polo no momento da medição. Por exemplo, o estado de qubit representado pela seta na figura a seguir tem uma probabilidade maior de dar o valor 0 se você medi-lo.
Você pode usar essa representação para visualizar o que o código está fazendo:
Primeiro, comece com um qubit inicializado no estado |0〉 e aplique uma
Hoperação para criar uma superposição igual na qual as probabilidades para 0 e 1 são as mesmas.
Em seguida, meça o qubit e salve a saída:
Como o resultado da medição é aleatório e as probabilidades de medir 0 e 1 são as mesmas, você obteve um bit completamente aleatório. Você pode chamar essa operação várias vezes para criar inteiros. Por exemplo, se você chamar a operação três vezes para obter três bits aleatórios, poderá criar números aleatórios de 3 bits (ou seja, um número aleatório entre 0 e 7).
Escreva um gerador de números aleatórios completo
Primeiro, você precisa importar os namespaces necessários da Q# biblioteca padrão para o programa. O Q# compilador carrega muitas funções e operações comuns automaticamente, no entanto, para o gerador de números aleatórios completo, você precisa de algumas funções e operações adicionais de dois Q# namespaces:
Std.MatheStd.Convert.import Std.Convert.*; import Std.Math.*;Em seguida, você define a
GenerateRandomNumberInRangeoperação. Esta operação chama repetidamente a operaçãoGenerateRandomBitpara criar uma cadeia 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 { 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 recapitular o novo código.
- Você precisa calcular o número de bits necessários para expressar inteiros até
max. A funçãoBitSizeIdo namespaceStd.Mathconverte um inteiro para o número de bits necessários para representá-lo. - A operação
SampleRandomNumberInRangeutiliza um ciclo deforpara gerar números aleatórios até gerar um que seja igual ou inferior amax. Oforloop funciona exatamente da mesma forma que umforloop em outras linguagens de programação. - A variável
bitsé uma variável mutável. Uma variável mutável é uma variável que pode mudar durante o cálculo. Utilize a diretivasetpara alterar o valor de uma variável mutável. - A
ResultArrayAsIntfunção, do namespace padrãoStd.Convert, converte a cadeia de bits em um inteiro positivo.
- Você precisa calcular o número de bits necessários para expressar inteiros até
Finalmente, você adiciona um ponto de entrada ao programa. Por padrão, o compilador procura por uma operação Q# e começa a processá-la lá. Ele chama a
GenerateRandomNumberInRangeoperação para gerar um número aleatório entre 0 e 100.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
letdeclara variáveis que não mudam durante o cálculo. Aqui você define o valor máximo como 100.Para obter mais informações sobre a
Mainoperação, consulte Pontos de entrada.O código completo para o gerador de números aleatórios é o seguinte:
import Std.Convert.*;
import Std.Math.*;
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 {
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 a Hadamard operation
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;
}
Execute o programa gerador de números aleatórios
Você pode executar o programa no Copilot no Azure Quantum e no 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 Explore Azure Quantum.
Abra o Copilot no Azure Quantum em seu navegador.
Copie e cole o código a seguir no editor de códigos.
import Std.Convert.*; import Std.Math.*; 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 { 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 disparos a serem executados e selecione Executar.
Os resultados são exibidos no histograma e nos campos Resultados .
Selecione Explicar código para solicitar que o Copilot explique o código para você.
Gorjeta
No Copilot no Azure Quantum, você pode abrir seu programa no VS Code para a Web selecionando o botão do logotipo do VS Code no canto direito do editor de código.
Nota
Atualmente, esse trecho de código não é executado em nenhum hardware targetsdisponível do Azure Quantum, pois o chamável ResultArrayAsInt requer uma QPU com um perfil de computação completo.
Conteúdos relacionados
Explore outros Q# tutoriais:
- O entrelaçamento quântico mostra como escrever um Q# programa que manipula e mede qubits e demonstra os efeitos da sobreposição e do emaranhamento.
- O algoritmo de pesquisa de Grover mostra como escrever um Q# programa que usa o algoritmo de pesquisa de Grover.
- Quantum Fourier Transforms 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.