[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.3516478340 |  1.1816456287 |  1.0001924199
     2 |      200 |  0.000000E+00 |  0.0192240408 |  1.1532524043 |  1.0001924199
     3 |      300 |  0.000000E+00 |  0.000000E+00 |  1.1005567442 |  1.0001924199
     4 |      400 |  0.000000E+00 |  0.000000E+00 |  1.0423303243 |  1.0001732916
     5 |      500 |  0.000000E+00 |  0.000000E+00 |  1.0214569210 |  1.0001143855
     6 |      600 |  0.000000E+00 |  0.000000E+00 |  1.0112639832 |  1.0001143855
     7 |      700 |  0.000000E+00 |  0.000000E+00 |  1.0063985649 |  1.0000835458
     8 |      800 |  0.000000E+00 |  0.000000E+00 |  1.0042655553 |  1.0000835458
     9 |      900 |  0.000000E+00 |  0.000000E+00 |  1.0029222610 |  1.0000804747
    10 |     1000 |  0.000000E+00 |  0.000000E+00 |  1.0017479510 |  1.0000540459
    11 |     1100 |  0.000000E+00 |  0.000000E+00 |  1.0008203740 |  1.0000448415
    12 |     1200 |  0.000000E+00 |  0.000000E+00 |  1.0001879254 |  1.0000426034
    13 |     1300 |  0.000000E+00 |  0.000000E+00 |  1.0001294281 |  1.0000414669
    14 |     1400 |  0.000000E+00 |  0.000000E+00 |  1.0001048756 |  1.0000414669
    15 |     1500 |  0.000000E+00 |  0.000000E+00 |  1.0000798570 |  1.0000414669
    16 |     1600 |  0.000000E+00 |  0.000000E+00 |  1.0000641902 |  1.0000400124
    17 |     1700 |  0.000000E+00 |  0.000000E+00 |  1.0000536662 |  1.0000400124
    18 |     1800 |  0.000000E+00 |  0.000000E+00 |  1.0000493836 |  1.0000398293
    19 |     1900 |  0.000000E+00 |  0.000000E+00 |  1.0000461424 |  1.0000395511
    20 |     2000 |  0.000000E+00 |  0.000000E+00 |  1.0000436532 |  1.0000395511
Best solution found:
X = [0.25000989 0.75002966]
F = [1.00003955]
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.0168997810 |  1.1966219666 |             - |             -
     2 |      200 |  0.0082848537 |  0.5046020034 |             - |             -
     3 |      300 |  0.0029693797 |  0.1776405901 |             - |             -
     4 |      400 |  0.0009258613 |  0.0596529505 |             - |             -
     5 |      500 |  0.0005056684 |  0.0288759017 |             - |             -
     6 |      600 |  0.0003567486 |  0.0169237558 |             - |             -
     7 |      700 |  0.0003567486 |  0.0121468316 |             - |             -
     8 |      800 |  0.0003567486 |  0.0085924525 |             - |             -
     9 |      900 |  0.0002721305 |  0.0056338874 |             - |             -
    10 |     1000 |  0.0002721305 |  0.0038791059 |             - |             -
    11 |     1100 |  0.0002721305 |  0.0022950025 |             - |             -
    12 |     1200 |  0.0002721305 |  0.0017183819 |             - |             -
    13 |     1300 |  0.0000264663 |  0.0013707858 |             - |             -
    14 |     1400 |  0.000000E+00 |  0.0012435913 |  1.3318479164 |  1.3318479164
    15 |     1500 |  0.000000E+00 |  0.0009793862 |  1.3318479164 |  1.3318479164
    16 |     1600 |  0.000000E+00 |  0.0007594017 |  1.3318479164 |  1.3318479164
    17 |     1700 |  0.000000E+00 |  0.0006334001 |  1.3301094441 |  1.3266896822
    18 |     1800 |  0.000000E+00 |  0.0005198833 |  1.3305265785 |  1.3266896822
    19 |     1900 |  0.000000E+00 |  0.0003956834 |  1.2728496075 |  1.0421417236
    20 |     2000 |  0.000000E+00 |  0.0002388947 |  1.3017516728 |  1.0421417236
Best solution found:
X = [0.26055515 0.78158657]
F = [1.04214172]
CV = [0.]