Exercício Parte 2 - Criar um gerador quântico de números aleatórios
Nesta unidade, você implementa a segunda parte do seu gerador de números aleatórios quânticos. Você combina vários bits aleatórios para formar um número aleatório maior. Esta parte baseia-se no gerador de bits aleatórios que você já criou na unidade anterior.
Combine vários bits aleatórios para formar um número maior
Na unidade anterior, você criou um gerador de bits aleatório que coloca um qubit em um estado de superposição e, em seguida, mede esse qubit para gerar um valor de bit aleatório de 0 ou 1, cada um com 50% de probabilidade. O valor deste bit é verdadeiramente aleatório, não há como saber com antecedência qual será o resultado da medição. Mas como você pode usar esse comportamento para gerar números aleatórios maiores?
Se você repetir o processo quatro vezes, então você pode gerar esta sequência de dígitos binários:
$${0, 1, 1, 0}$$
Se você combinar esses bits em uma cadeia de bits, poderá formar um número maior. Neste exemplo, a sequência de bits ${0110}$ em binário é equivalente ao número 6 em decimal.
$${0110_{\ binário} \equiv 6_{\ decimal}}$$
Para gerar um número aleatório arbitrariamente grande, basta repetir este processo muitas vezes. Em seguida, combine todos os bits em um número binário e converta esse número binário em um número decimal.
Definir a lógica do gerador de números aleatórios
Antes de escrever seu código Q#, vamos descrever a lógica para gerar um número aleatório:
- Defina
maxcomo o número decimal máximo que você deseja gerar. - Determine o número de bits aleatórios,
nBits, que são necessários para gerarmax. - Gere uma cadeia de bits aleatórios que tenha
nBitsde comprimento. - Se a cadeia de caracteres de bit representar um número maior que
max, volte para a etapa anterior. - De outro modo, o processo está concluído. Retorne o número gerado como um inteiro decimal.
Por exemplo, vamos definir max como sendo 12. Ou seja, 12 é o maior número que o seu gerador de números aleatórios deve produzir.
Use a seguinte equação para determinar o número de bits necessários para representar o número 12 em binário:
$${\lfloor ln(12) / ln(2) + 1 \rfloor}$$
De acordo com esta equação, você precisa de 4 bits para representar um número entre 0 e 12.
Por exemplo, suponha que você gere um bit aleatório quatro vezes e obtenha a cadeia de bits ${1101_{\ binário}}$. Este valor em binário é igual a 13 em decimal. Uma vez que 13 é maior que 12, repete-se o processo.
Em seguida, você gera a cadeia de bits ${0110_{\ binary}}$, que é igual a ${6_{\ decimal}}$. Uma vez que 6 é menor que 12, o processo está concluído.
O gerador de números aleatórios quânticos retorna o número 6.
Crie um gerador de números aleatórios completo em Q#
Aqui, você expande o Main.qs arquivo da lição anterior para construir seu gerador de números aleatórios.
Importar as bibliotecas necessárias
Primeiro, importe os namespaces da biblioteca padrão Q# que contêm as funções e operações necessárias para escrever seu programa. O compilador Q# carrega muitas funções e operações comuns automaticamente. Mas para o gerador de números aleatórios quânticos, você precisa de algumas funções e operações adicionais de dois namespaces Q#: Microsoft.Quantum.Math e Microsoft.Quantum.Convert.
Copie e cole as seguintes import diretivas no início do Main.qs arquivo:
import Std.Convert.*;
import Std.Math.*;
Nota
Você pode usar Std em vez de Microsoft.Quantum importar funções e operações da biblioteca padrão.
Renomeie a Main operação para GenerateRandomBit
O programa gerador de números aleatórios usa a Main operação que você escreveu na unidade anterior para gerar um bit aleatório. Renomeie a Main operação para GenerateRandomBit que ela tenha um nome mais descritivo e não seja o ponto de entrada para o programa.
Copie e cole o seguinte código em Main.qs:
import Std.Convert.*;
import Std.Math.*;
operation GenerateRandomBit() : Result {
// Allocate a qubit.
use q = Qubit();
// Set the qubit into superposition of 0 and 1 using the Hadamard
H(q);
// Measure the qubit and store the result.
let result = M(q);
// Reset qubit to the |0〉 state.
Reset(q);
// Return the result of the measurement.
return result;
}
Definir a operação do gerador de números aleatórios
Crie uma nova operação chamada GenerateRandomNumberInRange. Esta operação chama repetidamente a operação GenerateRandomBit para criar uma cadeia de bits.
Copie o código a seguir e coloque-o diretamente antes da GenerateRandomBit operação em seu Main.qs arquivo:
/// 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's within the requested range.
// Generate it again if it's outside the range.
return sample > max ? GenerateRandomNumberInRange(max) | sample;
}
Aqui está uma visão geral do código em GenerateRandomNumberInRange:
- Chame a
BitSizeIfunção daStd.Mathbiblioteca para calcular o número de bits necessários para representar o inteiro armazenado nomax. - Use um
forloop para gerar um número de bits aleatórios igual anBits. Chame a sua operaçãoGenerateRandomBitpara gerar bits aleatórios. - Dentro do
forloop, use a instruçãosetpara atualizar a variávelbitsa cada novo bit aleatório. A variávelbitsé uma variável mutável, o que significa que o valor debitspode mudar durante o cálculo. - Chame a função
ResultArrayAsIntda bibliotecaStd.Convertpara converter o array de bits embitsnum inteiro positivo armazenado emsample. -
returnNa declaração, verifique sesampleé maior quemax. Sesamplefor maior quemax, ligueGenerateRandomNumberInRangenovamente e comece de novo. Caso contrário, retorne o número aleatório armazenado emsample.
Adicionar um ponto de entrada
Finalmente, adicione uma operação de ponto de entrada ao seu código para que o compilador possa executar o programa. Por padrão, o compilador Q# procura uma Main operação e usa Main como ponto de entrada, não importa onde Main esteja localizado em seu arquivo. Aqui, a Main operação define um valor para max e chama a GenerateRandomNumberInRange operação para gerar um número aleatório entre 0 e max.
Por exemplo, para gerar um número aleatório entre 0 e 100, copie o seguinte código para o Main.qs arquivo:
operation Main() : Int {
let max = 100;
Message($"Generating a random number between 0 and {max}: ");
// Generate random number in the 0..max range.
return GenerateRandomNumberInRange(max);
}
Programa final
Aqui está o código Q# completo para o seu programa em Main.qs:
import Std.Convert.*;
import Std.Math.*;
operation Main() : Int {
let max = 100;
Message($"Generating 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's within the requested range.
// Generate it again if it's 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 operation
H(q);
// 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.
Reset(q);
// Return the result of the measurement.
return result;
}
Execute o programa
Experimente o seu novo gerador quântico de números aleatórios!
Para executar o programa, escolha a lente de código Executar na lista de comandos acima da Main operação. Ou pressione Ctrl + F5. Sua saída é exibida no console de depuração. Execute o programa várias vezes e observe como o resultado muda.
Parabéns! Você criou um gerador de números quânticos verdadeiramente aleatório em Q#.
Exercício de bónus
Tente modificar o programa para que ele também exija que o número aleatório gerado seja maior do que algum número positivo mínimo, minem vez de zero.