Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Multi-objective optimization framework. NSGA-II, NSGA-III, MOEA/D, Pareto fronts, constraint handling, benchmarks (ZDT, DTLZ), for engineering design and optimization problems.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | — | — |
| case-08 | ✗→✓ | ▲ Improved | — | — |
| case-09 | ✗→✓ | ▲ Improved | — | — |
| case-10 | ✗→✓ | ▲ Improved | — | — |
| case-19 | ✗→✓ | ▲ Improved | — | — |
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.
This skill should be used when:
Pymoo uses a consistent minimize() function for all optimization tasks:
pythonfrom 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 historySingle-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
When: Optimizing one objective function
Steps:
Example:
pythonfrom 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
When: Optimizing 2-3 conflicting objectives, need Pareto front
Algorithm choice: NSGA-II (standard for bi/tri-objective)
Steps:
Example:
pythonfrom 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
When: Optimizing 4 or more objectives
Algorithm choice: NSGA-III (designed for many objectives)
Key difference: Must provide reference directions for population guidance
Steps:
Example:
pythonfrom 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
When: Solving domain-specific optimization problem
Steps:
ElementwiseProblem class__init__ with problem dimensions and bounds_evaluate method for objectives (and constraints)Unconstrained example:
pythonfrom 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:
pythonclass 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:
g(x) <= 0 (feasible when ≤ 0)h(x) = 0 (feasible when = 0)g(x) >= b to -(g(x) - b) <= 0See: scripts/custom_problem_example.py for complete examples
When: Problem has feasibility constraints
Approach options:
1. Feasibility First (Default - Recommended)
pythonfrom 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)}")
2. Penalty Method
pythonfrom pymoo.constraints.as_penalty import ConstraintsAsPenalty # Wrap problem to convert constraints to penalties problem_penalized = ConstraintsAsPenalty(problem, penalty=1e6)
3. Constraint as Objective
pythonfrom pymoo.constraints.as_obj import ConstraintsAsObjective # Treat constraint violation as additional objective problem_with_cv = ConstraintsAsObjective(problem)
4. Specialized Algorithms
pythonfrom 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
When: Have Pareto front, need to select preferred solution(s)
Steps:
Example using Pseudo-Weights:
pythonfrom 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:
See:
scripts/decision_making_example.py for complete examplereferences/constraints_mcdm.md for detailed MCDM methodsChoose visualization based on number of objectives:
2 objectives: Scatter Plot
pythonfrom 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
pythonplot = Scatter(title="Tri-objective Results") plot.add(result.F) # Automatically renders in 3D plot.show()
4+ objectives: Parallel Coordinate Plot
pythonfrom 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
pythonfrom 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 | 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 |
| 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 |
| 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 |
| 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
pythonfrom 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
pythonfrom 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 )
Continuous variables:
Binary variables:
Permutations (TSP, scheduling):
See: references/operators.md for comprehensive operator reference
Problem: Algorithm not converging
Problem: Poor Pareto front distribution
Problem: Few feasible solutions
Problem: High computational cost
save_history=TrueThis skill includes comprehensive reference documentation and executable examples:
Detailed documentation for in-depth understanding:
Search patterns for references:
grep -r "NSGA-II\|NSGA-III\|MOEA/D" references/grep -r "Feasibility First\|Penalty\|Repair" references/grep -r "Scatter\|PCP\|Petal" references/Executable examples demonstrating common workflows:
Run examples:
bashpython3 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
Installation:
bashuv 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:
ElementwiseProblem for custom problemsg(x) <= 0 and h(x) = 0('n_gen', N) or get_termination("f_tol", tol=0.001)| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +50 percentage points is the difference between those two pass rates over the 22 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.