I think my first time generating random numbers was when I was working on my first neural network. I don’t remember my thought process anymore, but I remember wanting to find a better way to do it. It was during that time that I discovered the difference between true random numbers and pseudo-random numbers, and I’ve had true random number generation on my to-do list ever since.

For those who don’t know, most number generators are pseudo-random. An algorithm determines the next number, and so there is an element of predictability. True random number generators, on the other hand, are completely unpredictable. I’ve seen ones based on atmospheric noise and luminosity fluctuations, because you can’t predict nature. Therefore, I decided to make one using electrons in superposition states, because you can’t predict the next set of measurements.

I modelled my generator on Python’s random library. You can generate integers and floats either on a simulator (qrandint, quniform) or on an actual quantum computer (add a q: qqrandint, qquniform). As of this time, the randomness is based on the maximum quantum bits (qubits) available, which is either 32 simulated qubits or 14 real qubits.

It is worth noting that the simulator is relatively quick. You might wait several seconds for the result. Real hardware has a queue, however, so it is possible to wait several hours for your result. That may make quantum number generation impractical for real world applications, but I did this project simply because quantum everything is really, really cool.

It is also worth noting that you need an IBM Q Experience account to run this code, but registration is free.

At the time I am writing this, I have not actually tested this code on real hardware. It works on the simulator. However, I apparently used up all my credits during testing. All other bugs have been fixed, but now I get an out-of-credits error. I don’t know when my credits will be restored, so I’ll share this high-confidence code for now, and then update this later if I have to.

from qiskit import Aer, ClassicalRegister, execute, QuantumCircuit, QuantumRegister

from qiskit.tools.monitor import job_monitor

def qrandint(min, max):

range = max - min

qaddend = range * qmeasure('sim')

qsum = qaddend + min

qint = int(qsum +.5)

return qint

def qqrandint(min, max):

range = max - min

qaddend = range * qmeasure('real')

qsum = qaddend + min

qint = int(qsum +.5)

return qint

def quniform(min, max):

range = max - min

qaddend = range * qmeasure('sim')

qsum = qaddend + min

return qsum

def qquniform(min, max):

range = max - min

qaddend = range * qmeasure('real')

qsum = qaddend + min

return qsum

def qmeasure(hardware):

if (hardware == 'real'):

qubits = 14

IBMQ.load_account()

IBMQ.providers()

provider = IBMQ.get_provider(group='open')

provider.backends()

backend = provider.get_backend('ibmq_16_melbourne')

else:

qubits = 32

backend = Aer.get_backend('qasm_simulator')

q = QuantumRegister(qubits) # initialize all available quantum registers (qubits)

c = ClassicalRegister(qubits) # initialize classical registers to measure the qubits

qc = QuantumCircuit(q, c) # initialize the circuit

i = 0

while i < qubits:

qc.h(q[i]) # put all qubits into superposition states so that each will measure as a 0 or 1 completely at random

i = i + 1

qc.measure(q, c) # collapse the superpositions and get random zeroes and ones

job = execute(qc, backend=backend, shots=1, memory=True)

job_monitor(job)

result = job.result()

mraw = result.get_memory(qc)

m = str(mraw)

subtotal = 0

for i in range(qubits):

subtotal = subtotal + (int(m[i+2]) * 2**(i)) # convert each binary digit to its decimal value, but read left-to-right for simplicity

multiplier = subtotal / (2**qubits) # convert the measurement to a value between 0 and 1

return multiplier

#print(qrandint(-100, 100))

#print(quniform(-1, 1))

print(qqrandint(-100, 100))

#print(qquniform(-1, 1))