Pymoo - Multi-Objective Optimization in Python
Overview
Pymoo is a comprehensive Python framework for optimization with emphasis on multi-objective problems. Solve single and multi-objective optimization using state-of-the-art algorithms (NSGA-II/III, MOEA/D), benchmark problems (ZDT, DTLZ), customizable genetic operators, and multi-criteria decision making methods. Excels at finding trade-off solutions (Pareto fronts) for problems with conflicting objectives.
When to Use This Skill
This skill should be used when:
-
Solving optimization problems with one or multiple objectives
-
Finding Pareto-optimal solutions and analyzing trade-offs
-
Implementing evolutionary algorithms (GA, DE, PSO, NSGA-II/III)
-
Working with constrained optimization problems
-
Benchmarking algorithms on standard test problems (ZDT, DTLZ, WFG)
-
Customizing genetic operators (crossover, mutation, selection)
-
Visualizing high-dimensional optimization results
-
Making decisions from multiple competing solutions
-
Handling binary, discrete, continuous, or mixed-variable problems
Core Concepts
The Unified Interface
Pymoo uses a consistent minimize() function for all optimization tasks:
from pymoo.optimize import minimize
result = minimize( problem, # What to optimize algorithm, # How to optimize termination, # When to stop seed=1, verbose=True )
Result object contains:
-
result.X : Decision variables of optimal solution(s)
-
result.F : Objective values of optimal solution(s)
-
result.G : Constraint violations (if constrained)
-
result.algorithm : Algorithm object with history
Problem Types
Single-objective: One objective to minimize/maximize Multi-objective: 2-3 conflicting objectives → Pareto front Many-objective: 4+ objectives → High-dimensional Pareto front Constrained: Objectives + inequality/equality constraints Dynamic: Time-varying objectives or constraints
Quick Start Workflows
Workflow 1: Single-Objective Optimization
When: Optimizing one objective function
Steps:
-
Define or select problem
-
Choose single-objective algorithm (GA, DE, PSO, CMA-ES)
-
Configure termination criteria
-
Run optimization
-
Extract best solution
Example:
from pymoo.algorithms.soo.nonconvex.ga import GA from pymoo.problems import get_problem from pymoo.optimize import minimize
Built-in problem
problem = get_problem("rastrigin", n_var=10)
Configure Genetic Algorithm
algorithm = GA( pop_size=100, eliminate_duplicates=True )
Optimize
result = minimize( problem, algorithm, ('n_gen', 200), seed=1, verbose=True )
print(f"Best solution: {result.X}") print(f"Best objective: {result.F[0]}")
See: scripts/single_objective_example.py for complete example
Workflow 2: Multi-Objective Optimization (2-3 objectives)
When: Optimizing 2-3 conflicting objectives, need Pareto front
Algorithm choice: NSGA-II (standard for bi/tri-objective)
Steps:
-
Define multi-objective problem
-
Configure NSGA-II
-
Run optimization to obtain Pareto front
-
Visualize trade-offs
-
Apply decision making (optional)
Example:
from pymoo.algorithms.moo.nsga2 import NSGA2 from pymoo.problems import get_problem from pymoo.optimize import minimize from pymoo.visualization.scatter import Scatter
Bi-objective benchmark problem
problem = get_problem("zdt1")
NSGA-II algorithm
algorithm = NSGA2(pop_size=100)
Optimize
result = minimize(problem, algorithm, ('n_gen', 200), seed=1)
Visualize Pareto front
plot = Scatter() plot.add(result.F, label="Obtained Front") plot.add(problem.pareto_front(), label="True Front", alpha=0.3) plot.show()
print(f"Found {len(result.F)} Pareto-optimal solutions")
See: scripts/multi_objective_example.py for complete example
Workflow 3: Many-Objective Optimization (4+ objectives)
When: Optimizing 4 or more objectives
Algorithm choice: NSGA-III (designed for many objectives)
Key difference: Must provide reference directions for population guidance
Steps:
-
Define many-objective problem
-
Generate reference directions
-
Configure NSGA-III with reference directions
-
Run optimization
-
Visualize using Parallel Coordinate Plot
Example:
from pymoo.algorithms.moo.nsga3 import NSGA3 from pymoo.problems import get_problem from pymoo.optimize import minimize from pymoo.util.ref_dirs import get_reference_directions from pymoo.visualization.pcp import PCP
Many-objective problem (5 objectives)
problem = get_problem("dtlz2", n_obj=5)
Generate reference directions (required for NSGA-III)
ref_dirs = get_reference_directions("das-dennis", n_dim=5, n_partitions=12)
Configure NSGA-III
algorithm = NSGA3(ref_dirs=ref_dirs)
Optimize
result = minimize(problem, algorithm, ('n_gen', 300), seed=1)
Visualize with Parallel Coordinates
plot = PCP(labels=[f"f{i+1}" for i in range(5)]) plot.add(result.F, alpha=0.3) plot.show()
See: scripts/many_objective_example.py for complete example
Workflow 4: Custom Problem Definition
When: Solving domain-specific optimization problem
Steps:
-
Extend ElementwiseProblem class
-
Define init with problem dimensions and bounds
-
Implement _evaluate method for objectives (and constraints)
-
Use with any algorithm
Unconstrained example:
from pymoo.core.problem import ElementwiseProblem import numpy as np
class MyProblem(ElementwiseProblem): def init(self): super().init( n_var=2, # Number of variables n_obj=2, # Number of objectives xl=np.array([0, 0]), # Lower bounds xu=np.array([5, 5]) # Upper bounds )
def _evaluate(self, x, out, *args, **kwargs):
# Define objectives
f1 = x[0]**2 + x[1]**2
f2 = (x[0]-1)**2 + (x[1]-1)**2
out["F"] = [f1, f2]
Constrained example:
class ConstrainedProblem(ElementwiseProblem): def init(self): super().init( n_var=2, n_obj=2, n_ieq_constr=2, # Inequality constraints n_eq_constr=1, # Equality constraints xl=np.array([0, 0]), xu=np.array([5, 5]) )
def _evaluate(self, x, out, *args, **kwargs):
# Objectives
out["F"] = [f1, f2]
# Inequality constraints (g <= 0)
out["G"] = [g1, g2]
# Equality constraints (h = 0)
out["H"] = [h1]
Constraint formulation rules:
-
Inequality: Express as g(x) <= 0 (feasible when ≤ 0)
-
Equality: Express as h(x) = 0 (feasible when = 0)
-
Convert g(x) >= b to -(g(x) - b) <= 0
See: scripts/custom_problem_example.py for complete examples
Workflow 5: Constraint Handling
When: Problem has feasibility constraints
Approach options:
- Feasibility First (Default - Recommended)
from pymoo.algorithms.moo.nsga2 import NSGA2
Works automatically with constrained problems
algorithm = NSGA2(pop_size=100) result = minimize(problem, algorithm, termination)
Check feasibility
feasible = result.CV[:, 0] == 0 # CV = constraint violation print(f"Feasible solutions: {np.sum(feasible)}")
- Penalty Method
from pymoo.constraints.as_penalty import ConstraintsAsPenalty
Wrap problem to convert constraints to penalties
problem_penalized = ConstraintsAsPenalty(problem, penalty=1e6)
- Constraint as Objective
from pymoo.constraints.as_obj import ConstraintsAsObjective
Treat constraint violation as additional objective
problem_with_cv = ConstraintsAsObjective(problem)
- Specialized Algorithms
from pymoo.algorithms.soo.nonconvex.sres import SRES
SRES has built-in constraint handling
algorithm = SRES()
See: references/constraints_mcdm.md for comprehensive constraint handling guide
Workflow 6: Decision Making from Pareto Front
When: Have Pareto front, need to select preferred solution(s)
Steps:
-
Run multi-objective optimization
-
Normalize objectives to [0, 1]
-
Define preference weights
-
Apply MCDM method
-
Visualize selected solution
Example using Pseudo-Weights:
from pymoo.mcdm.pseudo_weights import PseudoWeights import numpy as np
After obtaining result from multi-objective optimization
Normalize objectives
F_norm = (result.F - result.F.min(axis=0)) / (result.F.max(axis=0) - result.F.min(axis=0))
Define preferences (must sum to 1)
weights = np.array([0.3, 0.7]) # 30% f1, 70% f2
Apply decision making
dm = PseudoWeights(weights) selected_idx = dm.do(F_norm)
Get selected solution
best_solution = result.X[selected_idx] best_objectives = result.F[selected_idx]
print(f"Selected solution: {best_solution}") print(f"Objective values: {best_objectives}")
Other MCDM methods:
-
Compromise Programming: Select closest to ideal point
-
Knee Point: Find balanced trade-off solutions
-
Hypervolume Contribution: Select most diverse subset
See:
-
scripts/decision_making_example.py for complete example
-
references/constraints_mcdm.md for detailed MCDM methods
Workflow 7: Visualization
Choose visualization based on number of objectives:
2 objectives: Scatter Plot
from pymoo.visualization.scatter import Scatter
plot = Scatter(title="Bi-objective Results") plot.add(result.F, color="blue", alpha=0.7) plot.show()
3 objectives: 3D Scatter
plot = Scatter(title="Tri-objective Results") plot.add(result.F) # Automatically renders in 3D plot.show()
4+ objectives: Parallel Coordinate Plot
from pymoo.visualization.pcp import PCP
plot = PCP( labels=[f"f{i+1}" for i in range(n_obj)], normalize_each_axis=True ) plot.add(result.F, alpha=0.3) plot.show()
Solution comparison: Petal Diagram
from pymoo.visualization.petal import Petal
plot = Petal( bounds=[result.F.min(axis=0), result.F.max(axis=0)], labels=["Cost", "Weight", "Efficiency"] ) plot.add(solution_A, label="Design A") plot.add(solution_B, label="Design B") plot.show()
See: references/visualization.md for all visualization types and usage
Algorithm Selection Guide
Single-Objective Problems
Algorithm Best For Key Features
GA General-purpose Flexible, customizable operators
DE Continuous optimization Good global search
PSO Smooth landscapes Fast convergence
CMA-ES Difficult/noisy problems Self-adapting
Multi-Objective Problems (2-3 objectives)
Algorithm Best For Key Features
NSGA-II Standard benchmark Fast, reliable, well-tested
R-NSGA-II Preference regions Reference point guidance
MOEA/D Decomposable problems Scalarization approach
Many-Objective Problems (4+ objectives)
Algorithm Best For Key Features
NSGA-III 4-15 objectives Reference direction-based
RVEA Adaptive search Reference vector evolution
AGE-MOEA Complex landscapes Adaptive geometry
Constrained Problems
Approach Algorithm When to Use
Feasibility-first Any algorithm Large feasible region
Specialized SRES, ISRES Heavy constraints
Penalty GA + penalty Algorithm compatibility
See: references/algorithms.md for comprehensive algorithm reference
Benchmark Problems
Quick problem access:
from pymoo.problems import get_problem
Single-objective
problem = get_problem("rastrigin", n_var=10) problem = get_problem("rosenbrock", n_var=10)
Multi-objective
problem = get_problem("zdt1") # Convex front problem = get_problem("zdt2") # Non-convex front problem = get_problem("zdt3") # Disconnected front
Many-objective
problem = get_problem("dtlz2", n_obj=5, n_var=12) problem = get_problem("dtlz7", n_obj=4)
See: references/problems.md for complete test problem reference
Genetic Operator Customization
Standard operator configuration:
from pymoo.algorithms.soo.nonconvex.ga import GA from pymoo.operators.crossover.sbx import SBX from pymoo.operators.mutation.pm import PM
algorithm = GA( pop_size=100, crossover=SBX(prob=0.9, eta=15), mutation=PM(eta=20), eliminate_duplicates=True )
Operator selection by variable type:
Continuous variables:
-
Crossover: SBX (Simulated Binary Crossover)
-
Mutation: PM (Polynomial Mutation)
Binary variables:
-
Crossover: TwoPointCrossover, UniformCrossover
-
Mutation: BitflipMutation
Permutations (TSP, scheduling):
-
Crossover: OrderCrossover (OX)
-
Mutation: InversionMutation
See: references/operators.md for comprehensive operator reference
Performance and Troubleshooting
Common issues and solutions:
Problem: Algorithm not converging
-
Increase population size
-
Increase number of generations
-
Check if problem is multimodal (try different algorithms)
-
Verify constraints are correctly formulated
Problem: Poor Pareto front distribution
-
For NSGA-III: Adjust reference directions
-
Increase population size
-
Check for duplicate elimination
-
Verify problem scaling
Problem: Few feasible solutions
-
Use constraint-as-objective approach
-
Apply repair operators
-
Try SRES/ISRES for constrained problems
-
Check constraint formulation (should be g <= 0)
Problem: High computational cost
-
Reduce population size
-
Decrease number of generations
-
Use simpler operators
-
Enable parallelization (if problem supports)
Best practices:
-
Normalize objectives when scales differ significantly
-
Set random seed for reproducibility
-
Save history to analyze convergence: save_history=True
-
Visualize results to understand solution quality
-
Compare with true Pareto front when available
-
Use appropriate termination criteria (generations, evaluations, tolerance)
-
Tune operator parameters for problem characteristics
Resources
This skill includes comprehensive reference documentation and executable examples:
references/
Detailed documentation for in-depth understanding:
-
algorithms.md: Complete algorithm reference with parameters, usage, and selection guidelines
-
problems.md: Benchmark test problems (ZDT, DTLZ, WFG) with characteristics
-
operators.md: Genetic operators (sampling, selection, crossover, mutation) with configuration
-
visualization.md: All visualization types with examples and selection guide
-
constraints_mcdm.md: Constraint handling techniques and multi-criteria decision making methods
Search patterns for references:
-
Algorithm details: grep -r "NSGA-II|NSGA-III|MOEA/D" references/
-
Constraint methods: grep -r "Feasibility First|Penalty|Repair" references/
-
Visualization types: grep -r "Scatter|PCP|Petal" references/
scripts/
Executable examples demonstrating common workflows:
-
single_objective_example.py: Basic single-objective optimization with GA
-
multi_objective_example.py: Multi-objective optimization with NSGA-II, visualization
-
many_objective_example.py: Many-objective optimization with NSGA-III, reference directions
-
custom_problem_example.py: Defining custom problems (constrained and unconstrained)
-
decision_making_example.py: Multi-criteria decision making with different preferences
Run examples:
python3 scripts/single_objective_example.py python3 scripts/multi_objective_example.py python3 scripts/many_objective_example.py python3 scripts/custom_problem_example.py python3 scripts/decision_making_example.py
Additional Notes
Installation:
pip install pymoo
Dependencies: NumPy, SciPy, matplotlib, autograd (optional for gradient-based)
Documentation: https://pymoo.org/
Version: This skill is based on pymoo 0.6.x
Common patterns:
-
Always use ElementwiseProblem for custom problems
-
Constraints formulated as g(x) <= 0 and h(x) = 0
-
Reference directions required for NSGA-III
-
Normalize objectives before MCDM
-
Use appropriate termination: ('n_gen', N) or get_termination("f_tol", tol=0.001)