Skip to content

Genetic generators

xopt.generators.ga.cnsga.CNSGAGenerator

CNSGAGenerator(**kwargs)

Bases: Generator

Constrained Non-dominated Sorting Genetic Algorithm (CNSGA) generator.

Attributes:

name : str The name of the generator. supports_multi_objective : bool Indicates if the generator supports multi-objective optimization. population_size : int The population size for the genetic algorithm. crossover_probability : float The probability of crossover. mutation_probability : float The probability of mutation. population_file : Optional[str] The file path to load the population from (CSV format). output_path : Optional[str] The directory path to save the population files. _children : List[Dict] The list of children generated. _offspring : Optional[pd.DataFrame] The DataFrame containing the offspring. population : Optional[pd.DataFrame] The DataFrame containing the population.

Methods:

create_children(self) -> List[Dict] Create children for the next generation. add_data(self, new_data: pd.DataFrame) Add new data to the generator. generate(self, n_candidates: int) -> List[Dict] Generate a specified number of candidate samples. write_offspring(self, filename: Optional[str] = None) Write the current offspring to a CSV file. write_population(self, filename: Optional[str] = None) Write the current population to a CSV file. load_population_csv(self, filename: str) Load a population from a CSV file. n_pop(self) -> int Convenience property for population_size.

Source code in xopt/generators/ga/cnsga.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
def __init__(self, **kwargs):
    super().__init__(**kwargs)

    self._loaded_population = (
        None  # use these to generate children until the first pop is made
    )

    # DEAP toolbox (internal)
    self._toolbox = cnsga_toolbox(self.vocs, selection="auto")

    if self.population_file is not None:
        self.load_population_csv(self.population_file)

    if self.output_path is not None:
        assert os.path.isdir(self.output_path), "Output directory does not exist"

Attributes

xopt.generators.ga.cnsga.CNSGAGenerator.n_pop property
n_pop

Convenience property for population_size.

Returns:

int The population size.

Functions

xopt.generators.ga.cnsga.CNSGAGenerator.add_data
add_data(new_data)

Add new data to the generator.

Parameters:

new_data : pd.DataFrame The new data to be added.

Source code in xopt/generators/ga/cnsga.py
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
def add_data(self, new_data: pd.DataFrame):
    """
    Add new data to the generator.

    Parameters:
    -----------
    new_data : pd.DataFrame
        The new data to be added.
    """
    if new_data is not None:
        self._offspring = pd.concat([self._offspring, new_data])

        # Next generation
        if len(self._offspring) >= self.n_pop:
            candidates = pd.concat([self.population, self._offspring])
            self.population = cnsga_select(
                candidates, self.n_pop, self.vocs, self._toolbox
            )

            if self.output_path is not None:
                self.write_offspring()
                self.write_population()

            self._children = []  # reset children
            self._offspring = None  # reset offspring
xopt.generators.ga.cnsga.CNSGAGenerator.create_children
create_children()

Create children for the next generation.

Returns:

List[Dict] A list of dictionaries containing the generated children.

Source code in xopt/generators/ga/cnsga.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
def create_children(self) -> List[Dict]:
    """
    Create children for the next generation.

    Returns:
    --------
    List[Dict]
        A list of dictionaries containing the generated children.
    """
    # No population, so create random children
    if self.population is None:
        # Special case when pop is loaded from file
        if self._loaded_population is None:
            return self.vocs.random_inputs(self.n_pop, include_constants=False)
        else:
            pop = self._loaded_population
    else:
        pop = self.population

    # Use population to create children
    inputs = cnsga_variation(
        pop,
        self.vocs,
        self._toolbox,
        crossover_probability=self.crossover_probability,
        mutation_probability=self.mutation_probability,
    )
    return inputs.to_dict(orient="records")
xopt.generators.ga.cnsga.CNSGAGenerator.generate
generate(n_candidates)

Generate a specified number of candidate samples.

Parameters:

n_candidates : int The number of candidate samples to generate.

Returns:

List[Dict] A list of dictionaries containing the generated samples.

Source code in xopt/generators/ga/cnsga.py
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
def generate(self, n_candidates: int) -> List[Dict]:
    """
    Generate a specified number of candidate samples.

    Parameters:
    -----------
    n_candidates : int
        The number of candidate samples to generate.

    Returns:
    --------
    List[Dict]
        A list of dictionaries containing the generated samples.
    """
    # Make sure we have enough children to fulfill the request
    while len(self._children) < n_candidates:
        self._children.extend(self.create_children())

    return [self._children.pop() for _ in range(n_candidates)]
xopt.generators.ga.cnsga.CNSGAGenerator.load_population_csv
load_population_csv(filename)

Load a population from a CSV file.

Parameters:

filename : str The file path to load the population from.

Source code in xopt/generators/ga/cnsga.py
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
def load_population_csv(self, filename: str):
    """
    Load a population from a CSV file.

    Parameters:
    -----------
    filename : str
        The file path to load the population from.
    """
    pop = pd.read_csv(filename, index_col="xopt_index")
    self._loaded_population = pop
    # This is a list of dicts
    self._children = self.vocs.convert_dataframe_to_inputs(
        pop[self.vocs.variable_names], include_constants=False
    ).to_dict(orient="records")
    logger.info(f"Loaded population of len {len(pop)} from file: {filename}")
xopt.generators.ga.cnsga.CNSGAGenerator.write_offspring
write_offspring(filename=None)

Write the current offspring to a CSV file.

Parameters:

filename : str, optional The file path to save the offspring. If None, a timestamped filename is generated.

Source code in xopt/generators/ga/cnsga.py
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
def write_offspring(self, filename: Optional[str] = None):
    """
    Write the current offspring to a CSV file.

    Parameters:
    -----------
    filename : str, optional
        The file path to save the offspring. If None, a timestamped filename is generated.
    """
    if self._offspring is None:
        logger.warning("No offspring to write")
        return

    if filename is None:
        timestamp = xopt.utils.isotime(include_microseconds=True).replace(":", "_")
        filename = f"{self.name}_offspring_{timestamp}.csv"
        filename = os.path.join(self.output_path, filename)

    self._offspring.to_csv(filename, index_label="xopt_index")
xopt.generators.ga.cnsga.CNSGAGenerator.write_population
write_population(filename=None)

Write the current population to a CSV file.

Parameters:

filename : str, optional The file path to save the population. If None, a timestamped filename is generated.

Source code in xopt/generators/ga/cnsga.py
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
def write_population(self, filename: Optional[str] = None):
    """
    Write the current population to a CSV file.

    Parameters:
    -----------
    filename : str, optional
        The file path to save the population. If None, a timestamped filename is generated.
    """
    if self.population is None:
        logger.warning("No population to write")
        return

    if filename is None:
        timestamp = xopt.utils.isotime(include_microseconds=True).replace(":", "_")
        filename = f"{self.name}_population_{timestamp}.csv"
        filename = os.path.join(self.output_path, filename)

    self.population.to_csv(filename, index_label="xopt_index")