Skip to content

[BUG] AGEMOEA2 division by zero error #751

@muazhari

Description

@muazhari

Checklist

  • I searched existing issues
  • I'm using the latest pymoo version

Bug Description

AGEMOEA 2 division by zero error when using below example code. Im using pymoo with commit id: 6e1cb88.

Minimal Code to Reproduce

class ContentStrategyProblem(ElementwiseProblem):
    def __init__(self):
        super().__init__(n_var=4, n_obj=2, xl=np.array([0.01, 0.01, 0.01, 0.0]), xu=np.array([1.0, 1.0, 1.0, 1.0]))

    def _evaluate(self, x, out, *args, **kwargs):
        source_influence, amplifier_effect, banter_strength, has_fst_intervention = x
        
        # Objective 1: Maximize engagement (we'll use a simplified formula)
        base_engagement = 1.5 if has_fst_intervention else 1
        engagement_score = (source_influence * amplifier_effect * banter_strength) * base_engagement
        
        # Objective 2: Minimize negative sentiment (hypothetical)
        negative_sentiment = 0.5 * has_fst_intervention + 0.1 * (1 - source_influence)

        out["F"] = [-engagement_score, negative_sentiment]

runner = RayParallelization(job_resources={})
optimization_problem = ContentStrategyProblem(
    # elementwise_runner=runner
)

agemoea2_algorithm = AGEMOEA2()

termination = get_termination("time", "00:01:00")
result = minimize(
    problem=optimization_problem,
    algorithm=agemoea2_algorithm,
    verbose=True,
    seed=1
)

Error Message

==========================================================
n_gen  |  n_eval  | n_nds  |      eps      |   indicator  
==========================================================
     1 |      100 |      6 |             - |             -
     2 |      200 |     11 |  0.0577279929 |         ideal
     3 |      300 |      6 |  0.1778856766 |         ideal
     4 |      400 |      8 |  0.0863211991 |         ideal
     5 |      500 |      9 |  0.0139915214 |         ideal
     6 |      600 |      4 |  0.0121387444 |         ideal
     7 |      700 |      3 |  0.2310262917 |         ideal
     8 |      800 |      2 |  0.1939060943 |         ideal
     9 |      900 |      5 |  0.3272611788 |         ideal
    10 |     1000 |      2 |  0.4087270492 |         ideal
    11 |     1100 |      6 |  0.1537786751 |         ideal
    12 |     1200 |      5 |  0.2311699925 |         ideal
    13 |     1300 |      8 |  0.0133638859 |         ideal
    14 |     1400 |      6 |  0.0330066173 |         ideal
    15 |     1500 |     10 |  0.5777152290 |         nadir
    16 |     1600 |      5 |  0.0441168778 |         ideal
    17 |     1700 |      7 |  0.0507478193 |             f
    18 |     1800 |      8 |  0.0034690261 |         nadir
    19 |     1900 |      7 |  0.0337110676 |         ideal
    20 |     2000 |     10 |  0.0058099718 |         ideal
    21 |     2100 |      8 |  0.0061289139 |         ideal
    22 |     2200 |      8 |  0.0098262262 |             f
    23 |     2300 |      9 |  0.0088472570 |         ideal
    24 |     2400 |      8 |  0.1296656299 |         ideal
    25 |     2500 |      2 |  0.1566509640 |         ideal
    26 |     2600 |      3 |  0.0279537565 |         ideal
    27 |     2700 |      4 |  0.0043663282 |         ideal
    28 |     2800 |      7 |  0.0417304699 |         ideal
    29 |     2900 |      8 |  0.0209455696 |         ideal
    30 |     3000 |     10 |  0.0219271875 |         ideal
    31 |     3100 |      9 |  0.0142879662 |         ideal
    32 |     3200 |     10 |  0.4389988711 |         nadir
    33 |     3300 |      6 |  0.0050860066 |         ideal
    34 |     3400 |      7 |  0.0395848263 |             f
    35 |     3500 |      7 |  0.9999775983 |         nadir
    36 |     3600 |      6 |  5.250872E+02 |         nadir
    37 |     3700 |      7 |  2.714909E+02 |         nadir
    38 |     3800 |      5 |  0.0026890043 |         ideal
    39 |     3900 |      8 |  0.9999724392 |         nadir
    40 |     4000 |      7 |  3.955529E+01 |         nadir
    41 |     4100 |      7 |  0.0028461624 |         ideal
    42 |     4200 |      9 |  0.0267046646 |         ideal
    43 |     4300 |     11 |  1.799695E+01 |         nadir
    44 |     4400 |      4 |  5.416172E+01 |         nadir
    45 |     4500 |      4 |  0.1193224803 |         ideal
    46 |     4600 |      8 |  0.0044991349 |         ideal
    47 |     4700 |     10 |  0.8980986769 |         nadir
    48 |     4800 |      6 |  0.0278943971 |         nadir
    49 |     4900 |      6 |  0.0430304756 |         ideal
    50 |     5000 |      7 |  0.0069831521 |         ideal
    51 |     5100 |      3 |  0.0136774367 |         ideal
    52 |     5200 |      5 |  0.0186564096 |         ideal
    53 |     5300 |      7 |  0.0293342425 |         ideal
    54 |     5400 |      8 |  0.0047865591 |         ideal
    55 |     5500 |      8 |  4.222404E+01 |         nadir
    56 |     5600 |      8 |  0.9401523120 |         nadir
    57 |     5700 |     11 |  0.0361796481 |         ideal
    58 |     5800 |     12 |  0.0029586325 |         ideal
    59 |     5900 |      6 |  0.0025969506 |         ideal
    60 |     6000 |     10 |  0.0032709755 |         ideal
    61 |     6100 |      8 |  1.9331520083 |         nadir
    62 |     6200 |      8 |  4.981988E+02 |         nadir
    63 |     6300 |      9 |  0.9999017070 |         nadir
    64 |     6400 |      2 |  0.2041693016 |         ideal
    65 |     6500 |      4 |  0.3043771353 |             f
    66 |     6600 |      3 |  0.2624973961 |             f
    67 |     6700 |      5 |  0.9999999998 |         nadir
    68 |     6800 |      6 |  5.9538163183 |         nadir
    69 |     6900 |      7 |  7.8606280362 |         nadir
    70 |     7000 |     10 |  0.0281788241 |         nadir
    71 |     7100 |      9 |  0.0031317177 |             f
    72 |     7200 |      8 |  0.8343467910 |         nadir
    73 |     7300 |      6 |  1.158527E+01 |         nadir
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
/tmp/ipykernel_34500/3814179118.py in <cell line: 0>()
     23 
     24 termination = get_termination("time", "00:01:00")
---> 25 result = minimize(
     26     problem=optimization_problem,
     27     algorithm=agemoea2_algorithm,

/usr/local/lib/python3.11/dist-packages/pymoo/optimize.py in minimize(problem, algorithm, termination, copy_algorithm, copy_termination, **kwargs)
     65 
     66     # actually execute the algorithm
---> 67     res = algorithm.run()
     68 
     69     # store the deep copied algorithm in the result object

/usr/local/lib/python3.11/dist-packages/pymoo/core/algorithm.py in run(self)
    136     def run(self):
    137         while self.has_next():
--> 138             self.next()
    139         return self.result()
    140 

/usr/local/lib/python3.11/dist-packages/pymoo/core/algorithm.py in next(self)
    157         if infills is not None:
    158             self.evaluator.eval(self.problem, infills, algorithm=self)
--> 159             self.advance(infills=infills)
    160 
    161         # if the algorithm does not follow the infill-advance scheme just call advance

/usr/local/lib/python3.11/dist-packages/pymoo/core/algorithm.py in advance(self, infills, **kwargs)
    223 
    224             # call the implementation of the advance method - if the infill is not None
--> 225             val = self._advance(infills=infills, **kwargs)
    226 
    227             # always advance to the next iteration - except if the algorithm returns False

/usr/local/lib/python3.11/dist-packages/pymoo/algorithms/base/genetic.py in _advance(self, infills, **kwargs)
    107 
    108         # execute the survival to find the fittest solutions
--> 109         self.pop = self.survival.do(self.problem, pop, n_survive=self.pop_size, algorithm=self, **kwargs)

/usr/local/lib/python3.11/dist-packages/pymoo/core/survival.py in do(self, problem, pop, n_survive, return_indices, *args, **kwargs)
     53 
     54         else:
---> 55             survivors = self._do(problem, pop, *args, n_survive=n_survive, **kwargs)
     56 
     57         if return_indices:

/usr/local/lib/python3.11/dist-packages/pymoo/algorithms/moo/age.py in _do(self, problem, pop, n_survive, *args, **kwargs)
    126 
    127         # Calculate the crowding distance of the first front as well as p and the normalization constants
--> 128         crowd_dist[front_no == 0], p, normalization = self.survival_score(front1, ideal_point)
    129         for i in range(1, max_f_no):  # skip first front since it is normalized by survival_score
    130             front = F[front_no == i, :]

/usr/local/lib/python3.11/dist-packages/pymoo/algorithms/moo/age.py in survival_score(self, front, ideal_point)
    171         nn[nn < 1e-8] = 1
    172 
--> 173         distances = self.pairwise_distances(front, p)
    174         distances[distances < 1e-8] = 1e-8  # Replace very small entries to prevent division by zero
    175 

ZeroDivisionError: division by zero

PyMoo & Python Version

pymoo @ git+https://github.com/anyoptimization/pymoo@main & python3.11

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions