[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.0190154493 |  1.1582876952 |  1.0001924199
     3 |      300 |  0.000000E+00 |  0.000000E+00 |  1.1007694294 |  1.0001924199
     4 |      400 |  0.000000E+00 |  0.000000E+00 |  1.0455278980 |  1.0000751839
     5 |      500 |  0.000000E+00 |  0.000000E+00 |  1.0240097894 |  1.0000751839
     6 |      600 |  0.000000E+00 |  0.000000E+00 |  1.0122687799 |  1.0000751839
     7 |      700 |  0.000000E+00 |  0.000000E+00 |  1.0065700992 |  1.0000751839
     8 |      800 |  0.000000E+00 |  0.000000E+00 |  1.0035541231 |  1.0000751839
     9 |      900 |  0.000000E+00 |  0.000000E+00 |  1.0020027789 |  1.0000734926
    10 |     1000 |  0.000000E+00 |  0.000000E+00 |  1.0011629318 |  1.0000734926
    11 |     1100 |  0.000000E+00 |  0.000000E+00 |  1.0006807512 |  1.0000673740
    12 |     1200 |  0.000000E+00 |  0.000000E+00 |  1.0002122873 |  1.0000443796
    13 |     1300 |  0.000000E+00 |  0.000000E+00 |  1.0001351986 |  1.0000427008
    14 |     1400 |  0.000000E+00 |  0.000000E+00 |  1.0001147938 |  1.0000427008
    15 |     1500 |  0.000000E+00 |  0.000000E+00 |  1.0000930356 |  1.0000427008
    16 |     1600 |  0.000000E+00 |  0.000000E+00 |  1.0000772331 |  1.0000394598
    17 |     1700 |  0.000000E+00 |  0.000000E+00 |  1.0000714031 |  1.0000394598
    18 |     1800 |  0.000000E+00 |  0.000000E+00 |  1.0000658372 |  1.0000394598
    19 |     1900 |  0.000000E+00 |  0.000000E+00 |  1.0000616017 |  1.0000394598
    20 |     2000 |  0.000000E+00 |  0.000000E+00 |  1.0000568967 |  1.0000394598
Best solution found:
X = [0.25000986 0.75002959]
F = [1.00003946]
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.5140031853 |             - |             -
     3 |      300 |  0.0082848537 |  0.2037348213 |             - |             -
     4 |      400 |  0.0035724722 |  0.0693818119 |             - |             -
     5 |      500 |  0.0027335643 |  0.0333759183 |             - |             -
     6 |      600 |  0.0020718948 |  0.0210356793 |             - |             -
     7 |      700 |  0.0008449391 |  0.0133758351 |             - |             -
     8 |      800 |  0.000000E+00 |  0.0096977061 |  1.2513217304 |  1.2513217304
     9 |      900 |  0.000000E+00 |  0.0071439108 |  1.2513217304 |  1.2513217304
    10 |     1000 |  0.000000E+00 |  0.0058541556 |  1.1754600320 |  1.0995983336
    11 |     1100 |  0.000000E+00 |  0.0052902209 |  1.1754600320 |  1.0995983336
    12 |     1200 |  0.000000E+00 |  0.0049327884 |  1.1754600320 |  1.0995983336
    13 |     1300 |  0.000000E+00 |  0.0043883970 |  1.1754600320 |  1.0995983336
    14 |     1400 |  0.000000E+00 |  0.0038476002 |  1.1754600320 |  1.0995983336
    15 |     1500 |  0.000000E+00 |  0.0034046822 |  1.1754600320 |  1.0995983336
    16 |     1600 |  0.000000E+00 |  0.0027531895 |  1.1754600320 |  1.0995983336
    17 |     1700 |  0.000000E+00 |  0.0022305012 |  1.1754600320 |  1.0995983336
    18 |     1800 |  0.000000E+00 |  0.0018260365 |  1.1754600320 |  1.0995983336
    19 |     1900 |  0.000000E+00 |  0.0014214863 |  1.1797710466 |  1.0995983336
    20 |     2000 |  0.000000E+00 |  0.0012825097 |  1.1797710466 |  1.0995983336
Best solution found:
X = [0.27488696 0.82471138]
F = [1.09959833]
CV = [0.]