# scipy.stats.qmc.QMCEngine

class scipy.stats.qmc.QMCEngine(d, *, seed=None)

  A generic Quasi-Monte Carlo sampler class meant for subclassing.

  QMCEngine is a base class to construct a specific Quasi-Monte Carlo sampler. It cannot be used directly as a sampler.

  Parameters
    d int

      Dimension of the parameter space.

    seed{None, int, `numpy.random.Generator`}, optional

      If seed is None the `numpy.random.Generator` singleton is used. If seed is an int, a new `Generator` instance is used, seeded with seed. If seed is already a `Generator` instance then that instance is used.

  Notes

  By convention samples are distributed over the half-open interval `[0, 1)`. Instances of the class can access the attributes: `d` for the dimension; and `rng` for the random number generator (used for the `seed`).

  Subclassing

  When subclassing `QMCEngine` to create a new sampler, `__init__` and `random` must be redefined.

  - `__init__(d, seed=None)`: at least fix the dimension. If the sampler does not take advantage of a `seed` (deterministic methods like Halton), this parameter can be omitted.

  - `random(n)`: draw `n` from the engine and increase the counter `num_generated` by `n`.

  Optionally, two other methods can be overwritten by subclasses:

  - `reset`: Reset the engine to it’s original state.

  - `fast_forward`: If the sequence is deterministic (like Halton sequence), then `fast_forward(n)` is skipping the `n` first draw.

  Examples

  To create a random sampler based on `np.random.random`, we would do the following:

      >>> from scipy.stats import qmc
      >>> class RandomEngine(qmc.QMCEngine):
      ...     def __init__(self, d, seed=None):
      ...         super().__init__(d=d, seed=seed)
      ...
      ...
      ...     def random(self, n=1):
      ...         self.num_generated += n
      ...         return self.rng.random((n, self.d))
      ...
      ...
      ...     def reset(self):
      ...         super().__init__(d=self.d, seed=self.rng_seed)
      ...         return self
      ...
      ...
      ...     def fast_forward(self, n):
      ...         self.random(n)
      ...         return self

  After subclassing `QMCEngine` to define the sampling strategy we want to use, we can create an instance to sample from.

      >>> engine = RandomEngine(2)
      >>> engine.random(5)
      array([[0.22733602, 0.31675834],  # random
             [0.79736546, 0.67625467],
             [0.39110955, 0.33281393],
             [0.59830875, 0.18673419],
             [0.67275604, 0.94180287]])

  We can also reset the state of the generator and resample again.

      >>> _ = engine.reset()
      >>> engine.random(5)
      array([[0.22733602, 0.31675834],  # random
             [0.79736546, 0.67625467],
             [0.39110955, 0.33281393],
             [0.59830875, 0.18673419],
             [0.67275604, 0.94180287]])

  Methods

  `fast_forward`(n) | Fast-forward the sequence by n positions.
  `random`([n]) | Draw n in the half-open interval `[0, 1)`.
  `reset`() | Reset the engine to base state.

Quasi-Monte Carlo submodule (`scipy.stats.qmc`) scipy.stats.qmc.QMCEngine.fast_forward