diff --git a/examples/quantum_mc.py b/examples/quantum_mc.py new file mode 100644 index 0000000..d125db0 --- /dev/null +++ b/examples/quantum_mc.py @@ -0,0 +1,46 @@ +""" +Run integration with qibo as the backend +and compares it to other algorithms +""" + +from vegasflow.quantum import quantum_wrapper, quantumflow_wrapper +from vegasflow import float_me, vegas_wrapper, plain_wrapper, run_eager +import time +import numpy as np +import tensorflow as tf + +run_eager(True) +# MC integration setup +dim = 2 +ncalls = int(1e5) +n_iter = 5 + + +def symgauss(xarr): + """symgauss test function""" + n_dim = xarr.shape[-1] + a = float_me(0.1) + n100 = float_me(100 * n_dim) + pref = tf.pow(1.0 / a / np.sqrt(np.pi), n_dim) + coef = tf.reduce_sum(tf.range(n100 + 1)) + coef += tf.reduce_sum(tf.square((xarr - 1.0 / 2.0) / a), axis=1) + coef -= (n100 + 1) * n100 / 2.0 + return pref * tf.exp(-coef) + + +def test_me(wrapper, nev): + nev = int(nev) + algo = wrapper.__name__.split("_")[0] + print(f"> Running {algo} for {nev} events") + start = time.time() + result = wrapper(symgauss, dim, n_iter, nev) + end = time.time() + print(f"This run took {end-start}\n") + return result + + +if __name__ == "__main__": + test_me(plain_wrapper, ncalls) + test_me(vegas_wrapper, ncalls) + test_me(quantum_wrapper, ncalls) + test_me(quantumflow_wrapper, ncalls) diff --git a/pyproject.toml b/pyproject.toml index bd43bc3..41dfe36 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,9 @@ dependencies = [ ] [project.optional-dependencies] +quantum = [ + "qibolab>=0.2.3" +] docs = [ 'sphinx', 'sphinx_rtd_theme', diff --git a/src/vegasflow/configflow.py b/src/vegasflow/configflow.py index 06f2cf2..ec2d063 100644 --- a/src/vegasflow/configflow.py +++ b/src/vegasflow/configflow.py @@ -56,7 +56,7 @@ # Create and format the log handler _console_handler = logging.StreamHandler() _console_handler.setLevel(_log_level) -_console_format = logging.Formatter("[%(levelname)s] (%(name)s) %(message)s") +_console_format = logging.Formatter("[%(levelname)s] %(message)s") _console_handler.setFormatter(_console_format) logger.addHandler(_console_handler) diff --git a/src/vegasflow/monte_carlo.py b/src/vegasflow/monte_carlo.py index b826faf..2a22ad8 100644 --- a/src/vegasflow/monte_carlo.py +++ b/src/vegasflow/monte_carlo.py @@ -246,6 +246,12 @@ def generate_random_array(self, n_events, *args): xjac = xjac_raw / (self.xjac * n_events) return rnds, xjac + def _internal_sampler(self, n_events): + """Latent uniform sampler to be digested by the MC algorithm""" + return tf.random.uniform( + (n_events, self.n_dim), minval=TECH_CUT, maxval=1.0 - TECH_CUT, dtype=DTYPE + ) + def _generate_random_array(self, n_events, *args): """Generate a 2D array of (n_events, n_dim) points For the weight of the given point, this function is considered @@ -261,9 +267,8 @@ def _generate_random_array(self, n_events, *args): `idx` : index associated to each random point `wgt` : wgt associated to the random point """ - rnds_raw = tf.random.uniform( - (n_events, self.n_dim), minval=TECH_CUT, maxval=1.0 - TECH_CUT, dtype=DTYPE - ) + rnds_raw = self._internal_sampler(n_events) + # Now allow for the algorithm to produce the random numbers for the integration rnds, wgts_raw, *extra = self._digest_random_generation(rnds_raw, *args) diff --git a/src/vegasflow/plain.py b/src/vegasflow/plain.py index bc60e90..4a1e175 100644 --- a/src/vegasflow/plain.py +++ b/src/vegasflow/plain.py @@ -1,5 +1,5 @@ """ - Plain implementation of the plainest possible MonteCarlo +Plain implementation of the plainest possible MonteCarlo """ import tensorflow as tf diff --git a/src/vegasflow/quantum.py b/src/vegasflow/quantum.py new file mode 100644 index 0000000..47cb0b0 --- /dev/null +++ b/src/vegasflow/quantum.py @@ -0,0 +1,77 @@ +""" +A Monte Carlo integrator built upon Qibo for quantum integration +""" + +import tensorflow as tf + +from .configflow import DTYPE, run_eager +from .monte_carlo import MonteCarloFlow, sampler, wrapper +from .plain import PlainFlow +from .vflow import VegasFlow + + +class QuantumBase(MonteCarloFlow): + """ + This class serves as a basis for the quantum monte carlo integrator. + At initialization it tries to import qibolab and connect to the quantum device, + if successful, saves the reference to _quantum_sampler. + + This class is compatible with all ``MonteCarloFlow`` classes, it overrides + the uniform sampling and uses the quantum device instead. + """ + + _CAN_RUN_VECTORIAL = False + + def __init__(self, *args, **kwargs): + # This integrator can only run for now in eager mode and needs qibolab to be installed + run_eager(True) + + try: + from qibolab.instruments.qrng import QRNG + from serial.serialutil import SerialException + except ModuleNotFoundError as e: + raise ModuleNotFoundError("You can do pip install vegasflow[quantum]") from e + + qaddress = "/dev/ttyACM0" + try: + # Check whether the quantum device is available and we can connect + qrng = QRNG(address=qaddress) + qrng.connect() + qrng.disconnect() + except SerialException as e: + raise SerialException(f"No quantum device found at {qaddress}") from e + + print(f"Sucessfuly connected to quantum device in {qaddress}") + + self._quantum_sampler = qrng + super().__init__(*args, **kwargs) + + def _internal_sampler(self, n_events): + """Sample ``n_events x n_dim`` numbers from the quantum device + and cast them to a TF DTYPE to pass down to the MC algorithm""" + self._quantum_sampler.connect() + quantum_rnds_raw = self._quantum_sampler.random((n_events, self.n_dim)) + self._quantum_sampler.disconnect() + return tf.cast(quantum_rnds_raw, dtype=DTYPE) + + +class QuantumIntegrator(PlainFlow, QuantumBase): + pass + + +class QuantumFlow(VegasFlow, QuantumBase): + pass + + +def quantum_wrapper(*args, **kwargs): + """Wrapper around QuantumIntegrator""" + return wrapper(QuantumIntegrator, *args, **kwargs) + + +def quantumflow_wrapper(*args, **kwargs): + return wrapper(QuantumFlow, *args, **kwargs) + + +def quantum_sampler(*args, **kwargs): + """Wrapper sampler around QuantumIntegrator""" + return sampler(QuantumIntegrator, *args, **kwargs) diff --git a/src/vegasflow/vflow.py b/src/vegasflow/vflow.py index 9096af6..9df58f9 100644 --- a/src/vegasflow/vflow.py +++ b/src/vegasflow/vflow.py @@ -1,8 +1,8 @@ """ - This module contains the VegasFlow class and all its auxiliary functions +This module contains the VegasFlow class and all its auxiliary functions - The main interfaces of this class are the class `VegasFlow` and the - `vegas_wrapper` +The main interfaces of this class are the class `VegasFlow` and the +`vegas_wrapper` """ import json diff --git a/src/vegasflow/vflowplus.py b/src/vegasflow/vflowplus.py index f329dec..2a833f9 100644 --- a/src/vegasflow/vflowplus.py +++ b/src/vegasflow/vflowplus.py @@ -1,10 +1,10 @@ """ - Implementation of vegas+ algorithm: +Implementation of vegas+ algorithm: - adaptive importance sampling + adaptive stratified sampling - from https://arxiv.org/abs/2009.05112 +adaptive importance sampling + adaptive stratified sampling +from https://arxiv.org/abs/2009.05112 - The main interface is the `VegasFlowPlus` class. +The main interface is the `VegasFlowPlus` class. """ from functools import partial