Ejercicio parte 2: Creación de un generador de números aleatorios cuántico
En esta unidad, implementará la segunda parte del generador de números aleatorios cuánticos. Se combinan varios bits aleatorios para formar un número aleatorio mayor. Esta parte se basa en el generador de bits aleatorio que ya creó en la unidad anterior.
Combinación de varios bits aleatorios para formar un número mayor
En la unidad anterior, creó un generador de bits aleatorio que coloca un cúbit en un estado de superposición y, a continuación, mide ese cúbit para generar un valor de bit aleatorio de 0 o 1, cada uno con 50% probabilidad. El valor de este bit es realmente aleatorio, no hay forma de saber con antelación cuál será el resultado de la medición. ¿Pero cómo puede usar este comportamiento para generar números aleatorios mayores?
Si repite el proceso cuatro veces, puede generar esta secuencia de dígitos binarios:
$${0, 1, 1, 0}$$
Si combina estos bits en una cadena de bits, puede formar un número mayor. En este ejemplo, la secuencia de bits ${0110}$ en binario equivale al número 6 en decimal.
$${0110_{\ binario} \equiv 6_{\ decimal}}$$
Para generar un número aleatorio arbitrariamente grande, simplemente repita este proceso muchas veces. A continuación, combine todos los bits en un número binario y convierta ese número binario en un número decimal.
Definición de la lógica del generador de números aleatorios
Antes de escribir el código de Q#, vamos a describir la lógica para generar un número aleatorio:
- Defina
maxcomo número decimal máximo que desea generar. - Determine el número de bits aleatorios,
nBits, necesarios para generarmax. - Generar una cadena de bits aleatorios que tenga una longitud de
nBits. - Si la cadena de bits representa un número mayor que
max, vuelva al paso anterior. - Si no, el proceso habrá finalizado. Devuelve el número generado como un entero decimal.
Por ejemplo, vamos a definir max como 12. Es decir, 12 es el número más grande que el generador de números aleatorios debe generar.
Use la siguiente ecuación para determinar el número de bits necesarios para representar el número 12 en binario:
$${\lfloor ln(12) / ln(2) + 1 \rfloor}$$
Según esta ecuación, necesita 4 bits para representar un número entre 0 y 12.
Por ejemplo, supongamos que genera un bit aleatorio cuatro veces y obtiene la cadena de bits ${1101_{\ binary}}$. Este valor en binario es igual a 13 en decimal. Como 13 es mayor que 12, repetimos el proceso.
A continuación, generará la cadena de bits ${0110_{\ binary}}$, que equivale a ${6_{\ decimal}}$. Dado que 6 es menor que 12, el proceso se ha completado.
El generador de números aleatorios cuántico devuelve el número 6.
Creación de un generador de números aleatorios completo en Q#
Aquí, amplía el archivo de la Main.qs lección anterior para construir tu generador de números aleatorios.
Importación de las bibliotecas necesarias
En primer lugar, importe los espacios de nombres de la biblioteca estándar de Q# que contienen las funciones y operaciones que necesita para escribir el programa. El compilador de Q# carga muchas funciones y operaciones comunes automáticamente. Pero para el generador de números aleatorios cuánticos, necesita algunas funciones y operaciones adicionales de dos espacios de nombres de Q#: Microsoft.Quantum.Math y Microsoft.Quantum.Convert.
Copie y pegue las siguientes import directivas al principio del Main.qs archivo:
import Std.Convert.*;
import Std.Math.*;
Nota:
Puede usar Std en lugar de Microsoft.Quantum para importar funciones y operaciones desde la biblioteca estándar.
Cambie el nombre de la operación Main a GenerateRandomBit
El programa de generador de números aleatorios usa la Main operación que escribió en la unidad anterior para generar un bit aleatorio. Cambie el nombre de la Main operación a GenerateRandomBit para que esta operación tenga un nombre más descriptivo y no sea el punto de entrada del programa.
Copie y pegue el código siguiente en 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 la operación del generador de números aleatorios
Cree una nueva operación denominada GenerateRandomNumberInRange. Esta operación llama repetidamente a la operación GenerateRandomBit para generar una cadena de bits.
Copie el código siguiente y colóquelo directamente antes de la operación GenerateRandomBit en su archivo Main.qs.
/// 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;
}
Esta es una introducción al código en GenerateRandomNumberInRange:
- Llame a la
BitSizeIfunción de laStd.Mathbiblioteca para calcular el número de bits necesarios para representar el entero almacenado enmax. - Use un
forbucle para generar un número de bits aleatorios igual anBits. Llame a la operaciónGenerateRandomBitpara generar los bits aleatorios. - Dentro del
forbucle, use lasetinstrucción para actualizar labitsvariable con cada nuevo bit aleatorio. La variable es una variablebitsmutable, lo que significa que el valor debitspuede cambiar durante el cálculo. - Llame a la
ResultArrayAsIntfunción de laStd.Convertbiblioteca para convertir la matriz de bits enbitsa un entero positivo almacenado ensample. - En la
returninstrucción , compruebe sisamplees mayor quemax. Sisamplees mayor quemax, llame aGenerateRandomNumberInRangede nuevo e inicie de nuevo. De lo contrario, devuelve el número aleatorio almacenado ensample.
Adición de un punto de entrada
Por último, agregue una operación de punto de entrada al código para que el compilador pueda ejecutar el programa. De forma predeterminada, el compilador de Q# busca una Main operación y usa Main como punto de entrada, independientemente de dónde Main se encuentre en el archivo. Aquí, la Main operación establece un valor para max y llama a la GenerateRandomNumberInRange operación para generar un número aleatorio entre 0 y max.
Por ejemplo, para generar un número aleatorio entre 0 y 100, copie el código siguiente en Main.qs el archivo:
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
Este es el código de Q# completo para el programa en 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;
}
Ejecución del programa
Pruebe el nuevo generador de números aleatorios cuánticos.
Para ejecutar el programa, desde la lista de comandos que hay encima de la operación Main, elija la lente de código Ejecutar. O bien, presione Ctrl + F5. La salida se muestra en la consola de depuración. Ejecute el programa varias veces y observe cómo cambia el resultado.
Felicidades. Ha creado un generador de números cuánticos verdaderamente aleatorios en Q#.
Ejercicio extra
Intente modificar el programa para que también requiera que el número aleatorio generado sea mayor que un número positivo mínimo, min, en lugar de cero.