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.
4This script demonstrates how to define a custom optimization problem
5and solve it using pymoo.
6"""
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)