Benchmark Problems

PyGAD bundles common benchmark problems under pygad.benchmarks. Each problem is a class callable with (ga, solution, sol_idx) and returns a fitness in PyGAD’s maximisation format. Minimisation values are negated.

Class attributes for setting up the GA:

  • num_genes: number of decision variables.

  • num_objectives: number of objectives (1 for single-objective).

  • bounds: (low, high) tuple of variable bounds.

ZDT classes also have a pareto_front(num_points) method that returns true-front reference points. Pass these to the IGD or GD indicators as reference_front.

A runnable example per benchmark lives under examples/benchmarks/.

Single-Objective Problems

Available in pygad.benchmarks.classic:

Class

Global minimum

Bounds

Sphere

f(0, …, 0) = 0

(-5.12, 5.12)

Rastrigin

f(0, …, 0) = 0

(-5.12, 5.12)

Rosenbrock

f(1, …, 1) = 0

(-5.0, 10.0)

Griewank

f(0, …, 0) = 0

(-600.0, 600.0)

Schwefel

f(420.97, …, 420.97) ≈ 0

(-500.0, 500.0)

Ackley

f(0, …, 0) = 0

(-32.768, 32.768)

Himmelblau

four equal minima at f = 0 (2D only)

(-5.0, 5.0)

Multi-Objective Problems (ZDT family)

In pygad.benchmarks.zdt. Two objectives, variables in [0, 1] (ZDT4 uses [-5, 5] for the rest).

Class

Pareto front shape

ZDT1

convex

ZDT2

non-convex

ZDT3

disconnected (five pieces)

ZDT4

convex, many local minima in the search space

ZDT6

non-uniform

Many-Objective Problems (DTLZ family)

In pygad.benchmarks.dtlz. Any number of objectives M. Decision variables: M + k - 1, where k is the distance-variable count.

Class

Default M

Pareto front shape

DTLZ1

3

linear hyperplane (sum(f_i) = 0.5)

DTLZ2

3

unit sphere first orthant

DTLZ3

3

unit sphere with hard multimodal g-function

DTLZ4

3

unit sphere with strong bias toward one corner

Combinatorial Problems

Two combinatorial benchmarks: 0/1 Knapsack and TSP.

Knapsack

In pygad.benchmarks.knapsack. Knapsack takes three arguments: 1D arrays of weights and values, and a numeric capacity. A solution is a binary vector (1 = pick the item). Fitness is the total value within capacity, or a negative penalty scaled by the overweight amount.

Class attributes gene_space=[0, 1] and gene_type=int plug into PyGAD as is:

import pygad
from pygad.benchmarks.knapsack import Knapsack

problem = Knapsack(weights=[2, 3, 4, 5],
                   values=[3, 4, 5, 6],
                   capacity=5)

ga = pygad.GA(
    num_generations=50,
    num_parents_mating=10,
    fitness_func=problem,
    sol_per_pop=30,
    num_genes=problem.num_genes,
    gene_space=problem.gene_space,
    gene_type=problem.gene_type,
)
ga.run()

Travelling Salesman Problem

In pygad.benchmarks.tsp. Build TSP from either a 2D coordinates array or a square distance_matrix. A solution is a permutation of city indices and the fitness is the negative tour length (the tour closes back to the start). Non-permutation candidates get a large negative penalty.

Class attributes gene_space=list(range(num_cities)), gene_type=int, and allow_duplicate_genes=False keep the permutation constraint:

import pygad
from pygad.benchmarks.tsp import TSP

problem = TSP(coordinates=[[0.0, 0.0],
                           [1.0, 0.0],
                           [1.0, 1.0],
                           [0.0, 1.0]])

ga = pygad.GA(
    num_generations=200,
    num_parents_mating=10,
    fitness_func=problem,
    sol_per_pop=30,
    num_genes=problem.num_genes,
    gene_space=problem.gene_space,
    gene_type=problem.gene_type,
    allow_duplicate_genes=problem.allow_duplicate_genes,
)
ga.run()

Example: SOO

import pygad
from pygad.benchmarks.classic import Sphere

problem = Sphere(num_genes=10)

ga = pygad.GA(
    num_generations=100,
    num_parents_mating=10,
    fitness_func=problem,
    sol_per_pop=20,
    num_genes=problem.num_genes,
    init_range_low=problem.bounds[0],
    init_range_high=problem.bounds[1],
    crossover_type='sbx',
    sbx_crossover_eta=30,
    mutation_type='polynomial',
    polynomial_mutation_eta=20,
)
ga.run()

Example: MOO

import pygad
from pygad.benchmarks.zdt import ZDT1
from pygad.utils.quality_indicators import inverted_generational_distance

problem = ZDT1(num_genes=10)

ga = pygad.GA(
    num_generations=200,
    num_parents_mating=20,
    fitness_func=problem,
    sol_per_pop=30,
    num_genes=problem.num_genes,
    init_range_low=problem.bounds[0],
    init_range_high=problem.bounds[1],
    parent_selection_type='nsga2',
    crossover_type='sbx',
    sbx_crossover_eta=30,
    mutation_type='polynomial',
    polynomial_mutation_eta=20,
)
ga.run()

# IGD against the true front.
true_front = problem.pareto_front(num_points=100)
igd = inverted_generational_distance(ga.last_generation_fitness, true_front)
print(f'IGD = {igd}')