Repair Operator

[1]:
%%capture
%run ./index.ipynb

Repair Operator#

A simple approach is to handle constraints through a repair function. This is only possible if the equation of the constraint is known. The repair makes sure every solution that is evaluated is, in fact, feasible. Let us consider the equality constraint example.

Let us define a Repair operator that always satisfies the equality constraint (the inequality constraint is simply ignored and will be figured out by the algorithm).

[2]:
from pymoo.core.repair import Repair

class MyRepair(Repair):

    def _do(self, problem, X, **kwargs):
        X[:, 0] = 1/3 * X[:, 1]
        return X

Now the algorithm object needs to be initialized with the Repair operator and then can be run to solve the problem:

[3]:
from pymoo.algorithms.soo.nonconvex.ga import GA
from pymoo.optimize import minimize

algorithm = GA(repair=MyRepair())

res = minimize(ConstrainedProblemWithEquality(),
               algorithm,
               ('n_gen', 20),
               seed=1,
               verbose=True)

print("Best solution found: \nX = %s\nF = %s\nCV = %s" % (res.X, res.F, res.CV))
=================================================================================
n_gen  |  n_eval  |     cv_min    |     cv_avg    |     f_avg     |     f_min
=================================================================================
     1 |      100 |  0.000000E+00 |  0.3621675497 |  1.1485625824 |  1.0040402769
     2 |      200 |  0.000000E+00 |  0.0158069271 |  1.1498265069 |  1.0040402769
     3 |      300 |  0.000000E+00 |  0.000000E+00 |  1.0718734487 |  1.0037909824
     4 |      400 |  0.000000E+00 |  0.000000E+00 |  1.0264063007 |  1.0005680041
     5 |      500 |  0.000000E+00 |  0.000000E+00 |  1.0135248142 |  1.0005680041
     6 |      600 |  0.000000E+00 |  0.000000E+00 |  1.0079679473 |  1.0004249358
     7 |      700 |  0.000000E+00 |  0.000000E+00 |  1.0041360700 |  1.0003566881
     8 |      800 |  0.000000E+00 |  0.000000E+00 |  1.0030012306 |  1.0002548659
     9 |      900 |  0.000000E+00 |  0.000000E+00 |  1.0021661237 |  1.0002548659
    10 |     1000 |  0.000000E+00 |  0.000000E+00 |  1.0013170367 |  1.0002548659
    11 |     1100 |  0.000000E+00 |  0.000000E+00 |  1.0007981978 |  1.0002548659
    12 |     1200 |  0.000000E+00 |  0.000000E+00 |  1.0005585282 |  1.0002322437
    13 |     1300 |  0.000000E+00 |  0.000000E+00 |  1.0004702926 |  1.0002322437
    14 |     1400 |  0.000000E+00 |  0.000000E+00 |  1.0004153861 |  1.0002101821
    15 |     1500 |  0.000000E+00 |  0.000000E+00 |  1.0003517422 |  1.0002101821
    16 |     1600 |  0.000000E+00 |  0.000000E+00 |  1.0003141463 |  1.0002100191
    17 |     1700 |  0.000000E+00 |  0.000000E+00 |  1.0002773131 |  1.0001809339
    18 |     1800 |  0.000000E+00 |  0.000000E+00 |  1.0002411187 |  1.0001788899
    19 |     1900 |  0.000000E+00 |  0.000000E+00 |  1.0002244580 |  1.0001788899
    20 |     2000 |  0.000000E+00 |  0.000000E+00 |  1.0002157044 |  1.0001747918
Best solution found:
X = [0.2500437  0.75013109]
F = [1.00017479]
CV = [0.]

If you would like to compare the solution without a repair you will see how searching only in the feasible space helps:

[4]:
from pymoo.algorithms.soo.nonconvex.ga import GA
from pymoo.optimize import minimize


algorithm = GA()

res = minimize(ConstrainedProblemWithEquality(),
               algorithm,
               ('n_gen', 20),
               seed=1,
               verbose=True)

print("Best solution found: \nX = %s\nF = %s\nCV = %s" % (res.X, res.F, res.CV))
=================================================================================
n_gen  |  n_eval  |     cv_min    |     cv_avg    |     f_avg     |     f_min
=================================================================================
     1 |      100 |  0.0101808244 |  1.2505054323 |             - |             -
     2 |      200 |  0.0088255124 |  0.4965367190 |             - |             -
     3 |      300 |  0.0030724079 |  0.2476582052 |             - |             -
     4 |      400 |  0.0016607398 |  0.1208656844 |             - |             -
     5 |      500 |  0.0001622390 |  0.0598781939 |             - |             -
     6 |      600 |  0.0001622390 |  0.0259155713 |             - |             -
     7 |      700 |  0.0001622390 |  0.0174156380 |             - |             -
     8 |      800 |  0.0001622390 |  0.0112338474 |             - |             -
     9 |      900 |  0.0001571776 |  0.0071670057 |             - |             -
    10 |     1000 |  0.0001314248 |  0.0052259997 |             - |             -
    11 |     1100 |  0.0001314248 |  0.0041169119 |             - |             -
    12 |     1200 |  0.0001314248 |  0.0034804459 |             - |             -
    13 |     1300 |  1.823665E-07 |  0.0027195562 |             - |             -
    14 |     1400 |  0.000000E+00 |  0.0022023378 |  1.2884812540 |  1.2524952187
    15 |     1500 |  0.000000E+00 |  0.0018922102 |  1.2884812540 |  1.2524952187
    16 |     1600 |  0.000000E+00 |  0.0015428272 |  1.2884812540 |  1.2524952187
    17 |     1700 |  0.000000E+00 |  0.0011870588 |  1.2884812540 |  1.2524952187
    18 |     1800 |  0.000000E+00 |  0.0010150449 |  1.2977760558 |  1.2524952187
    19 |     1900 |  0.000000E+00 |  0.0009024870 |  1.3043750371 |  1.2524952187
    20 |     2000 |  0.000000E+00 |  0.0007492699 |  1.3113910652 |  1.2524952187
Best solution found:
X = [0.31314134 0.93935388]
F = [1.25249522]
CV = [0.]