Exercício Parte 2 - Criar um gerador quântico de números aleatórios
Nesta unidade, você implementa a segunda fase do seu gerador quântico de números aleatórios: combinando vários bits aleatórios para formar um número aleatório maior. Esta fase 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 gera um bit aleatório colocando um qubit em superposição e medindo-o.
Quando você mede o qubit, você obterá um bit aleatório, 0 ou 1, com igual probabilidade de 50%. O valor desse bit é realmente aleatório, não há como saber o que você obtém após a medição. 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_{\ binary} \equiv 6_{\ decimal}}$$
Se você repetir esse processo muitas vezes, poderá combinar vários bits para formar qualquer número grande.
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 o gerador de bits aleatórios construído na unidade anterior:
- Defina
max
como o número máximo que você deseja gerar. - Defina o número de bits aleatórios que você precisa gerar calculando quantos bits,
nBits
, você precisa expressar inteiros atémax
. - Gere uma cadeia de bits aleatórios que tenha
nBits
de 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 obter do gerador de números aleatórios.
Você precisa de ${\lfloor ln(12) / ln(2) + 1 \rfloor}$, ou 4 bits para representar um número entre 0 e 12. (Por uma questão de brevidade, ignoramos como derivar esta equação.)
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 retorna o número 6.
Crie um gerador de números aleatórios completo
Aqui, você expande o Main.qs
arquivo para criar números aleatórios maiores.
Importar as bibliotecas necessárias
Primeiro, você precisa importar os namespaces necessários da biblioteca Q# Standard para o programa. O compilador Q# carrega muitas funções e operações comuns automaticamente, no entanto, para o gerador de números aleatórios quânticos completo, 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 na parte superior do arquivo Main.qs
:
import Microsoft.Quantum.Convert.*;
import Microsoft.Quantum.Math.*;
Renomeie a Main
operação para GenerateRandomBit
Para o gerador de números aleatórios completo, você vai reutilizar a operação definida na unidade anterior. No entanto, o nome Main
da operação é o ponto de entrada do programa e deve ser exclusivo. Para evitar confusão, você precisa renomear a Main
operação para GenerateRandomBit
.
A GenerateRandomBit
operação deve ter esta aparência:
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 número aleatório quântico
Aqui, define a operação GenerateRandomNumberInRange
. Esta operação chama repetidamente a operação GenerateRandomBit
para criar uma cadeia de bits.
Copie o código a seguir e cole-o 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 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
. ABitSizeI
função da biblioteca converteMicrosoft.Quantum.Math
um inteiro para o número de bits necessários para representá-lo. - A operação
GenerateRandomNumberInRange
utiliza um ciclo defor
para gerar números aleatórios até gerar um que seja igual ou inferior amax
. 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 é uma variável que pode mudar durante o cálculo. Utilize a diretivaset
para alterar o valor de uma variável mutável. - A
ResultArrayAsInt
função vem daMicrosoft.Quantum.Convert
biblioteca. Esta função converte a cadeia de bits para um número inteiro positivo.
Adicionar um ponto de entrada
Finalmente, você adiciona um ponto de entrada ao programa. Por padrão, o compilador Q# procura uma Main
operação e começa a processar lá, não importa onde ela esteja localizada. A Main
operação chama a GenerateRandomNumberInRange
operação para gerar um número aleatório entre 0 e um max
número. Neste exemplo, você define o valor máximo como 100.
Copie e cole o seguinte código no seu Main.qs
ficheiro:
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);
}
Programa final
O seu Main.qs
ficheiro deve ter o seguinte aspeto:
import Microsoft.Quantum.Convert.*;
import Microsoft.Quantum.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 {
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 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
Vamos experimentar o novo gerador de números aleatórios!
- Antes de executar o programa, você precisa definir o perfil de destino como Irrestrito. Selecione Exibir>Paleta de Comandos, procure QIR, selecione Q#: Definir o perfil de destino do Azure Quantum QIR e selecione Q#: irrestrito.
- Para executar o programa, selecione Executar na lista de comandos acima da
Main
operação ou pressione Ctrl+F5. Sua saída aparecerá no console de depuração. - Execute o programa novamente para ver um resultado diferente.
Nota
Se o perfil de destino não estiver definido como Sem restrições, você receberá um erro ao executar o programa.
Parabéns! Agora já sabe como combinar lógica clássica com o Q# para criar um gerador quântico de números aleatórios.
Exercício de bónus
Tente modificar o programa para também exigir que o número aleatório gerado seja maior do que algum número mínimo, min
em vez de zero.