Skill Tracer
Skills › Scientific Agent Skills › pymoo › custom_problem_example.py

custom_problem_example.py

188 lines · skills/pymoo/scripts/custom_problem_example.py at 5f2bc03

1"""
2Custom problem definition example using pymoo.
3
4This script demonstrates how to define a custom optimization problem
5and solve it using pymoo.
6"""
7
8from pymoo.core.problem import ElementwiseProblem
9from pymoo.algorithms.moo.nsga2 import NSGA2
10from pymoo.optimize import minimize
11from pymoo.visualization.scatter import Scatter
12import numpy as np
15class MyBiObjectiveProblem(ElementwiseProblem):
16 """
17 Custom bi-objective optimization problem.
19 Minimize:
20 f1(x) = x1^2 + x2^2
21 f2(x) = (x1-1)^2 + (x2-1)^2
23 Subject to:
24 0 <= x1 <= 5
25 0 <= x2 <= 5
26 """
28 def __init__(self):
29 super().__init__(
30 n_var=2, # Number of decision variables
31 n_obj=2, # Number of objectives
32 n_ieq_constr=0, # Number of inequality constraints
33 n_eq_constr=0, # Number of equality constraints
34 xl=np.array([0, 0]), # Lower bounds
35 xu=np.array([5, 5]) # Upper bounds
36 )
38 def _evaluate(self, x, out, *args, **kwargs):
39 """Evaluate objectives for a single solution."""
40 # Objective 1: Distance from origin
41 f1 = x[0]**2 + x[1]**2
43 # Objective 2: Distance from (1, 1)
44 f2 = (x[0] - 1)**2 + (x[1] - 1)**2
46 # Return objectives
47 out["F"] = [f1, f2]
50class ConstrainedProblem(ElementwiseProblem):
51 """
52 Custom constrained bi-objective problem.
54 Minimize:
55 f1(x) = x1
56 f2(x) = (1 + x2) / x1
58 Subject to:
59 x2 + 9*x1 >= 6 (g1 <= 0)
60 -x2 + 9*x1 >= 1 (g2 <= 0)
61 0.1 <= x1 <= 1
62 0 <= x2 <= 5
63 """
65 def __init__(self):
66 super().__init__(
67 n_var=2,
68 n_obj=2,
69 n_ieq_constr=2, # Two inequality constraints
70 xl=np.array([0.1, 0.0]),
71 xu=np.array([1.0, 5.0])
72 )
74 def _evaluate(self, x, out, *args, **kwargs):
75 """Evaluate objectives and constraints."""
76 # Objectives
77 f1 = x[0]
78 f2 = (1 + x[1]) / x[0]
80 out["F"] = [f1, f2]
82 # Inequality constraints (g <= 0)
83 # Convert g1: x2 + 9*x1 >= 6 → -(x2 + 9*x1 - 6) <= 0
84 g1 = -(x[1] + 9 * x[0] - 6)
86 # Convert g2: -x2 + 9*x1 >= 1 → -(-x2 + 9*x1 - 1) <= 0
87 g2 = -(-x[1] + 9 * x[0] - 1)
89 out["G"] = [g1, g2]
92def solve_custom_problem():
93 """Solve custom bi-objective problem."""
95 print("="*60)
96 print("CUSTOM PROBLEM - UNCONSTRAINED")
97 print("="*60)
99 # Define custom problem
100 problem = MyBiObjectiveProblem()
102 # Configure algorithm
103 algorithm = NSGA2(pop_size=40)
105 # Solve
106 result = minimize(
107 problem,
108 algorithm,
109 ('n_gen', 50),
110 seed=1,
111 verbose=False
112 )
114 print(f"Number of solutions: {len(result.F)}")
115 print(f"Objective space range:")
116 print(f" f1: [{result.F[:, 0].min():.3f}, {result.F[:, 0].max():.3f}]")
117 print(f" f2: [{result.F[:, 1].min():.3f}, {result.F[:, 1].max():.3f}]")
119 # Visualize
120 plot = Scatter(title="Custom Bi-Objective Problem")
121 plot.add(result.F, color="blue", alpha=0.7)
122 plot.show()
124 return result
127def solve_constrained_problem():
128 """Solve custom constrained problem."""
130 print("\n" + "="*60)
131 print("CUSTOM PROBLEM - CONSTRAINED")
132 print("="*60)
134 # Define constrained problem
135 problem = ConstrainedProblem()
137 # Configure algorithm
138 algorithm = NSGA2(pop_size=40)
140 # Solve
141 result = minimize(
142 problem,
143 algorithm,
144 ('n_gen', 50),
145 seed=1,
146 verbose=False
147 )
149 # A constrained run can return no feasible optimum.
150 if result.F is None:
151 print("[FAIL] No feasible solution was found.")
152 return result
153 feasible = result.opt.get("FEAS").ravel()
154 # Recheck the original equations, not only aggregated CV.
155 _, G = problem.evaluate(result.X, return_values_of=["F", "G"])
156 if not np.all(G[feasible] <= 0):
157 raise ValueError("Selected candidates violate the original constraints")
159 print(f"Total solutions: {len(result.F)}")
160 print(f"Feasible solutions: {np.sum(feasible)}")
161 print(f"Infeasible solutions: {np.sum(~feasible)}")
163 if np.any(feasible):
164 F_feasible = result.F[feasible]
165 print(f"\nFeasible objective space range:")
166 print(f" f1: [{F_feasible[:, 0].min():.3f}, {F_feasible[:, 0].max():.3f}]")
167 print(f" f2: [{F_feasible[:, 1].min():.3f}, {F_feasible[:, 1].max():.3f}]")
169 # Visualize feasible solutions
170 plot = Scatter(title="Constrained Problem - Feasible Solutions")
171 plot.add(F_feasible, color="green", alpha=0.7, label="Feasible")
173 if np.any(~feasible):
174 plot.add(result.F[~feasible], color="red", alpha=0.3, s=10, label="Infeasible")
176 plot.show()
178 return result
181if __name__ == "__main__":
182 # Run both examples
183 result1 = solve_custom_problem()
184 result2 = solve_constrained_problem()
186 print("\n" + "="*60)
187 print("EXAMPLES COMPLETED")
188 print("="*60)