Skip to content

grid_sampler


Overview

Creates a grid of equidistant points that spans bounds and num samples. i.e., (num_samples)**(len(parameters))


GridSampler

GridSampler(bounds, num_samples, parameters, *args, **kwargs)

Bases: Sampler

Configuration

To use the grid sampler, you need to specify it in the configuration file as follows:

   sampler:
      type: GridSampler
      parameters: ['x', 'y']
      bounds: [[1, 10], [0, 1]]
      num_samples: [4, 3]
In this configuration: - parameter x is sampled at 4 evenly spaced points between 1 and 10 - parameter y is sampled at 3 evenly spaced points between 0 and 1 - resulting in a total of 4 × 3 = 12 samples.

Attributes:

Name Type Description
bounds list of tuple of float

The bounds of each parameter.

num_samples list of int

The number of samples for each parameter.

parameters list of str

The names of the parameters.

total_budget int

The total number of parameter combinations.

num_initial_points int

The number of initial points in the sample space.

samples list of list of float

The generated parameter combinations.

current_index int

The index of the current parameter combination.

sampler_interface S

The type of sampler interface.


Assumptions and Notes

  • The sampler assumes continuous numeric parameters.
  • Parameter values are generated using numpy.linspace, resulting in evenly spaced points that include both bounds. The total number of samples (budget) is the product of num_samples across all parameters.
  • Grid size grows exponentially with the number of parameters; careful configuration is recommended. This throws errors if you are asking for something insane, e.g., 10 parameters for 10 samples each -> 10 billion. To prevent excessive memory usage, the sampler enforces a hard limit of 100,000 total samples.

Initializes the Grid sampler.

Parameters:

Name Type Description Default
bounds list of tuple of float

The bounds of each parameter.

required
num_samples list of int

The number of samples for each parameter.

required
parameters list of str

The names of the parameters.

required
Source code in src/enchanted_surrogates/samplers/grid_sampler.py
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
def __init__(self, bounds, num_samples, parameters, *args, **kwargs):
    """
    Initializes the Grid sampler.

    Args:
        bounds (list of tuple of float): The bounds of each parameter.
        num_samples (list of int): The number of samples for each parameter.
        parameters (list of str): The names of the parameters.
    """
    super().__init__()

    if isinstance(num_samples, int):
        num_samples = [num_samples] * len(parameters)

    self.parameters = parameters
    self.bounds = bounds
    self.num_samples = num_samples
    # check for stupidity
    self.budget = np.prod(np.array(num_samples))
    self.batch_size = kwargs.get("batch_size", self.budget)

    if self.budget > 100000:
        raise Exception(
            (
                "Can not do grid search on more than 10000 samples, ",
                f"you requested {self.budget}",
            )
        )

    self.samples = list(self.generate_parameters())
    self.current_index = 0

generate_parameters

generate_parameters()

Generates the parameter combinations.

Yields:

Type Description

list of float: The next parameter combination.

Source code in src/enchanted_surrogates/samplers/grid_sampler.py
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def generate_parameters(self):
    """
    Generates the parameter combinations.

    Yields:
        list of float: The next parameter combination.
    """
    samples = [
        np.linspace(self.bounds[i][0], self.bounds[i][1], self.num_samples[i])
        for i in range(len(self.bounds))
    ]
    # Use itertools.product to create a Cartesian product of sample
    # points, representing the hypercube
    for params_tuple in product(*samples):
        # Convert tuples to list to ensure serializability
        yield list(params_tuple)

get_next_samples

get_next_samples()

Gets the next batch of parameter combinations.

Returns:

Type Description
list[dict]

list[dict]: A batch of parameter combinations.

Source code in src/enchanted_surrogates/samplers/grid_sampler.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
def get_next_samples(self) -> list[dict]:
    """
    Gets the next batch of parameter combinations.

    Returns:
        list[dict]: A batch of parameter combinations.
    """
    list_param_dicts = []

    for _ in range(self.batch_size):
        if self.current_index >= len(self.samples):
            break
        params = self.samples[self.current_index]
        self.current_index += 1
        param_dict = {k: v for k, v in zip(self.parameters, params)}
        list_param_dicts.append(param_dict)

    self.submitted += len(list_param_dicts)
    return list_param_dicts

register_future

register_future(future)

Doesn't matter for grid sampler.

Source code in src/enchanted_surrogates/samplers/grid_sampler.py
127
128
129
def register_future(self, future):
    """Doesn't matter for grid sampler."""
    return None