API Reference¶
⚠️ Important Notice: This document is AI-generated based on source-code analysis. Although we strive for accuracy, inconsistencies or issues may still exist. We are actively improving and validating all content. If you encounter any problems, please report them promptly.
Core Classes¶
Problem¶
Class that defines a multi-objective optimisation problem.
Constructor:
Parameters:
objectives
(list[callable]): List of objective functions. Each function takes coords (n_points, 2) and returns a scalar.n_points
(int or list[int]): Number of coordinate points to optimise. Can be a fixed integer (e.g.,10
) or a list[min, max]
to allow the number of points to vary within a range during optimization.region
(shapely.geometry.Polygon): Shapely polygon defining the feasible region.constraints
(list, optional): List of constraint functions. Default is an empty list.penalty_weight
(float, optional): Weight applied to constraint violations. Default is 1e6.
Methods:
sample_population(pop_size)¶
Generate an initial population.
Parameters:
pop_size
(int): Population size.
Returns:
numpy.ndarray
: Population array with shape(pop_size, n_points, 2)
.
evaluate(population, n_jobs=1)¶
Evaluate the objective values for all individuals in a population. Uses serial computation when n_jobs=1 and parallel computation when n_jobs≠1.
Parameters:
population
(numpy.ndarray): Population with shape(pop_size, n_points, 2)
.n_jobs
(int, optional): Number of jobs for parallel computation. Default is 1 (serial computation). Set to -1 to use all available CPU cores, or any other value to specify the number of cores to use.
Returns:
numpy.ndarray
: Array of objective values with shape(n_objectives, pop_size)
.
Parallel Computation Notes:
- When to use parallel computation: Parallel processing is recommended for problems with computationally intensive objective functions or constraints. It's particularly effective for large populations or when each evaluation takes significant time.
- When NOT to use parallel computation: For simple optimization problems with fast objective functions, the overhead of parallel processing may reduce performance. In these cases, serial computation (n_jobs=1) is recommended.
- Example use cases for parallel computation:
- Complex simulations in each objective function
- Large population sizes (>100 individuals)
- Objective functions involving numerical integration or differential equations
Problems with many coordinate points
When to use parallel computation: Parallel processing is most beneficial for computationally intensive objective functions or constraints, such as those involving complex simulations, numerical integrations, or when evaluating large populations. It's particularly effective when each individual evaluation takes significant time (>0.01s).
- When NOT to use parallel computation: For simple and fast objective functions, the overhead of parallel processing may outweigh its benefits. If individual evaluations are very quick (<0.001s), serial computation may be more efficient.
- Performance considerations: The speedup from parallel computation depends on the number of available CPU cores and the computational complexity of the objective functions. The overhead of parallelization becomes negligible as the complexity of objective functions increases.
Example:
CoordsNSGA2¶
NSGA-II optimiser for coordinate problems.
Constructor:
Parameters:
problem
(Problem): Problem instance.pop_size
(int): Population size (must be even).prob_crs
(float): Crossover probability in the range 0-1.prob_mut
(float): Mutation probability in the range 0-1.random_seed
(int, optional): Random seed. Default is 42.n_jobs
(int, optional): Number of jobs for parallel computation. Default is 1 (serial computation). Set to -1 to use all available CPU cores, or any other value to specify the number of cores to use.
Attributes:
P
: Current population, shape(pop_size, n_points, 2)
.values_P
: Objective values of the current population, shape(n_objectives, pop_size)
.P_history
: Population history.values_history
: List of objective-value arrays per generation, each with shape(n_objectives, pop_size)
.
Methods:
run(generations, verbose=True)¶
Run the optimization algorithm.
Parameters:
generations
(int): Number of generations.verbose
(bool, optional): Show progress bar ifTrue
. Default isTrue
.
Returns:
numpy.ndarray
: Final population.
save(path)¶
Save the optimiser state to a pkl file.
Parameters:
path
(str): File path to save to.s
load(path)¶
Load the optimiser state from a pkl file.
Parameters:
path
(str): File path to load from.
Example:
Spatial Utilities¶
region_from_points(points)¶
Create a polygon region from a list of points.s
Parameters:
points
(list): List of points in the form[[x1, y1], [x2, y2], ...]
.
Returns:
shapely.geometry.Polygon
: Shapely polygon object.
Example:
region_from_range(x_min, x_max, y_min, y_max)¶
Create a rectangular region from coordinate bounds.
Parameters:
x_min
(float): Minimum x-coordinate.x_max
(float): Maximum x-coordinate.y_min
(float): Minimum y-coordinate.y_max
(float): Maximum y-coordinate.
Returns:
shapely.geometry.Polygon
: Shapely rectangle object.
Example:
create_points_in_polygon(polygon, n)¶
Generate n
random points inside a polygon.
Parameters:
polygon
(shapely.geometry.Polygon): Target polygon.n
(int): Number of points to generate.
Returns:
numpy.ndarray
: Array of coordinates with shape(n, 2)
.
Example:
Genetic Operators¶
coords_crossover(population, prob_crs)¶
Coordinate-specific crossover operator that exchanges subsets of points between parents.
Parameters:
population
(numpy.ndarray): Population with shape(pop_size, n_points, 2)
.prob_crs
(float): Crossover probability.
Returns:
numpy.ndarray
: Population after crossover.
Algorithm:
- For each parent pair, perform crossover with probability
prob_crs
. - Randomly select between 1 and
n_points-1
points to swap. - Population size remains unchanged.
Example:
coords_mutation(population, prob_mut, region)¶
Coordinate-specific mutation operator that relocates points randomly within the region.
Parameters:
population
(numpy.ndarray): Population with shape(pop_size, n_points, 2)
.prob_mut
(float): Mutation probability.region
(shapely.geometry.Polygon): Feasible region.
Returns:
numpy.ndarray
: Population after mutation.
Algorithm:
- For each coordinate point, mutate with probability
prob_mut
. - During mutation, generate a new random position within the region.
- Ensure mutated points remain inside the feasible region.
Example:
coords_selection(population, values_P, tourn_size=3)¶
Tournament selection based on non-dominated sorting and crowding distance.
Parameters:
population
(numpy.ndarray): Population with shape(pop_size, n_points, 2)
.values_P
(numpy.ndarray): Objective values with shape(n_objectives, pop_size)
.tourn_size
(int, optional): Tournament size. Default is3
Returns:
numpy.ndarray
: Selected population.
Algorithm:
- Use fast non-dominated sorting to assign front ranks.
- Compute crowding distance within each front.
- Apply tournament selection, preferring individuals in lower fronts.
- When ranks tie, choose individuals with larger crowding distance.
Example:
Utility Functions¶
fast_non_dominated_sort(objectives)¶
Fast non-dominated sorting algorithm.
Parameters:
objectives
(numpy.ndarray): Objective values with shape(n_objectives, pop_size)
.
Returns:
list
: List of fronts; each front contains the indices of individuals in that front.
Algorithm:
- Count how many times each individual is dominated.
- Record which individuals each one dominates.
- Return indices grouped by front.
- Sort individuals by front rank.
Example:
crowding_distance(objectives)¶
Compute crowding distance.
Parameters:
objectives
(numpy.ndarray): Objective values with shape(n_objectives, pop_size)
.
Returns:
numpy.ndarray
: Array of crowding distances.
Algorithm
- Sort individuals for each objective.
- Set boundary points’ crowding distance to infinity.
- For interior points, sum the normalised differences of adjacent objective values.
- Return distances in the original order.
Example: