Source code for qibolab._core.instruments.qrng.qrng
from typing import List, Optional, Sequence, Union
import numpy as np
import numpy.typing as npt
from serial import Serial
from ..abstract import Instrument
from .extractors import Extractor, ShaExtractor
__all__ = ["QRNG"]
def read(port: Serial, n: int = 1, nbytes: int = 4) -> List[int]:
"""Read raw samples from the QRNG device serial output.
In the entropy mode of the device, these typically follow a
normal distribution.
Args:
n: Number of samples to retrieve.
nbytes: Number of bytes to read from serial port to generate one raw sample.
"""
samples = []
while len(samples) < n:
num_str = ""
while len(num_str) < nbytes:
sample = port.read(1)
if sample == b" ":
break
num_str += sample.decode("utf-8")
try:
samples.append(int(num_str))
except ValueError:
pass
return samples
[docs]class QRNG(Instrument):
"""Driver to sample numbers from a Quantum Random Number Generator (QRNG).
See :ref:`qrng` for example usage.
"""
address: str
baudrate: int = 115200
extractor: Extractor = ShaExtractor()
port: Optional[Serial] = None
bytes_per_number: int = 4
"""Number of bytes to read from serial port to generate one raw sample."""
[docs] def read(self, n: int) -> List[int]:
"""Read raw samples from the QRNG device serial output.
In the entropy mode of the device, these typically follow a
normal distribution.
Args:
n: Number of samples to retrieve.
"""
return read(self.port, n, self.bytes_per_number)
[docs] def random(self, size: Optional[Union[int, Sequence[int]]] = None) -> npt.NDArray:
"""Returns random floats following uniform distribution in [0, 1].
Args:
size: Shape of the returned array (to behave similarly to ``np.random.random``).
"""
n = np.prod(size)
nraw = self.extractor.num_raw_samples(n)
raw = self.read(nraw)
extracted = self.extractor.extract(raw)[:n]
return np.reshape(extracted, size)