Parte 2 do Exercício: Criar um gerador quântico de números aleatórios
Nesta unidade, você implementa a segunda parte do gerador de número aleatório quântico. Você combina vários bits aleatórios para formar um número aleatório maior. Essa parte se baseia no gerador de bits aleatório 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% probabilidade. O valor desse bit é realmente aleatório, não há como saber antecipadamente qual será o resultado da medida. Mas como você pode usar esse comportamento para gerar números aleatórios maiores?
Se você repetir o processo quatro vezes, poderá gerar essa 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 mais amplo. Neste exemplo, a sequência de bits ${0110}$ em binário é equivalente ao número 6 em decimal.
$${0110_{\ binary} \equiv 6_{\ decimal}}$$
Para gerar um número aleatório arbitrariamente grande, basta repetir esse 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 o 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,
nBitsque são necessários para gerarmax. - 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 anterior. - Caso contrário, o processo está concluído. Retornar o número gerado como um inteiro decimal.
Por exemplo, vamos definir max como 12. Ou seja, 12 é o maior número que o gerador de número aleatório deve gerar.
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 essa 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 caracteres de bit ${1101_{\ binary}}$. Esse valor em binário é igual a 13 em decimais. Como 13 é maior que 12, você repete o processo.
Em seguida, você gera a cadeia de caracteres de bit ${0110_{\ binary}}$, que é igual a ${6_{\ decimal}}$. Já que 6 é menor que 12, o processo é concluído.
O gerador de números aleatórios quântico retorna o número 6.
Criar um gerador de número aleatório completo em Q#
Aqui, você expande o Main.qs arquivo da lição anterior para criar seu gerador de número aleatório.
Importar as bibliotecas necessárias
Primeiro, importe os namespaces da biblioteca padrão Q# que contêm as funções e as operações necessárias para gravar seu programa. O compilador Q# carrega várias funções e operações comuns automaticamente. Mas para o gerador de número aleatório quântico, você precisa de algumas funções e operações adicionais de dois namespaces de 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.*;
Observação
Você pode usar Std em vez de Microsoft.Quantum importar funções e operações da biblioteca padrão.
Renomeie a operação Main como GenerateRandomBit
O programa gerador de número aleatório 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 essa operação 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 de gerador de número aleatório
Criar uma nova operação chamada GenerateRandomNumberInRange. Essa operação chama repetidamente a operação GenerateRandomBit para criar uma cadeia de caracteres 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 emmax. - Use um
forloop para gerar vários bits aleatórios iguais anBits. Chame suaGenerateRandomBitfunção para gerar os bits aleatórios. - Dentro do loop
for, use a instruçãosetpara atualizar a variávelbitscom cada novo bit aleatório. A variávelbitsé uma variável mutável, o que significa que o valorbitspode ser alterado durante a computação. - Chame a função
ResultArrayAsIntda bibliotecaStd.Convertpara converter a matriz de bits embitsem um inteiro positivo armazenado emsample. - Na instrução
return, verifique sesampleé maior quemax. Sesamplefor maior quemax, ligueGenerateRandomNumberInRangenovamente e comece de novo. Caso contrário, retorne o número aleatório armazenado emsample.
Adicione um ponto de entrada
Por fim, adicione uma operação de ponto de entrada ao código para que o compilador possa executar seu 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 do 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;
}
Executar o programa
Experimente seu novo gerador de número aleatório quântico!
Para executar seu programa, escolha a lente de código Executar na lista de comandos acima da operação Main. 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úmero quântico realmente 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 que algum número positivo mínimo, minem vez de zero.