Individual__fitness_values: [{'Area': -0.001055561155631351, 'PowerDissipation': -1.00077, 'SlewRate': 0.0, 'Gain': -198.16899999999998, 'Bandwidth3dB': 0.0, 'GainBWProd': 0.0, 'UnityGainFreq': 0.0, 'PhaseMargin': -40.24199999999996}, 
{'Area': -0.0012086061530096081, 'PowerDissipation': -0.981954, 'SlewRate': 0.0, 'Gain': -62.612999999999985, 'Bandwidth3dB': -5.044702000000001, 'GainBWProd': -0.527294, 'UnityGainFreq': -2.65473, 'PhaseMargin': 0.0}, 
{'Area': -0.0013371072000520645, 'PowerDissipation': -12.835700000000001, 'SlewRate': 0.0, 'Gain': -104.45300000000003, 'Bandwidth3dB': -1.6747999999999998, 'GainBWProd': 0.0, 'UnityGainFreq': 0.0, 'PhaseMargin': 0.0}, 
{'Area': -0.001220563727286024, 'PowerDissipation': -1.7093099999999999, 'SlewRate': 0.0, 'Gain': -119.22600000000003, 'Bandwidth3dB': -2.1403399999999992, 'GainBWProd': 0.0, 'UnityGainFreq': 0.0, 'PhaseMargin': -13.739999999999995}]

in the Area and Bandwidth3dB it is very less difference, in the SlewRate, GainBWOrid there is no difference between the population, but in the PowerDissipation, Gain and the Phasemargin we are having large difference between these populations.

Area: -0.0008902637332358967 (A) < -0.0006251527703134982 (B) -> B is better
Area: -0.0006251527703134982 (A) > -0.0008902637332358967 (B) -> A is better
PowerDissipation: -0.6735829999999999 (A) > -1.6390899999999997 (B) -> A is better
Gain: -103.77000000000002 (A) < -76.18000000000002 (B) -> B is better
Area: -0.0008902637332358967 (A) < -0.0007166243050894572 (B) -> B is better
Area: -0.0007166243050894572 (A) > -0.0008902637332358967 (B) -> A is better
PowerDissipation: -5.720689999999999 (A) < -1.6390899999999997 (B) -> B is better
Area: -0.0008902637332358967 (A) > -0.0010705385787853593 (B) -> A is better
PowerDissipation: -1.6390899999999997 (A) < -1.01456 (B) -> B is better
Area: -0.0010705385787853593 (A) < -0.0008902637332358967 (B) -> B is better
Area: -0.0006251527703134982 (A) > -0.0007166243050894572 (B) -> A is better
PowerDissipation: -0.6735829999999999 (A) > -5.720689999999999 (B) -> A is better
Gain: -103.77000000000002 (A) < -82.55299999999998 (B) -> B is better
Area: -0.0007166243050894572 (A) < -0.0006251527703134982 (B) -> B is better
Area: -0.0006251527703134982 (A) > -0.0010705385787853593 (B) -> A is better
PowerDissipation: -0.6735829999999999 (A) > -1.01456 (B) -> A is better
Gain: -103.77000000000002 (A) < -43.05099999999996 (B) -> B is better
Area: -0.0010705385787853593 (A) < -0.0006251527703134982 (B) -> B is better
Area: -0.0007166243050894572 (A) > -0.0010705385787853593 (B) -> A is better
PowerDissipation: -5.720689999999999 (A) < -1.01456 (B) -> B is better
Area: -0.0010705385787853593 (A) < -0.0007166243050894572 (B) -> B is better

here we can see that mostly, Area and PowerDissipation are only being compared between the A and B, why not all the objectives were not compared between the each two individual chromosomes and choose whether it is dominant or not, the objective goal of implementing multi-objective optimization criteria to be maintain and synchronized in all aspects.

i am getting the all the individual chromosomes in the total population as my Non-dominated sets, i didnot get any domination count (an individual is dominated by other individual). i tried many iteration for all the iteration i am getting the same results.

Non-dominated sets: [[0, 1, 2, 3]]
Domination Count: [0, 0, 0, 0]

# Perform Pareto fronts with crowding distances and hypervolume
def pareto_sort(population, fitness_values, objectives):
    non_dominated_sets = []
    domination_counts = [0] * len(population)
    dominated_by = [[] for _ in population]
    
    # Compare each pair of individuals
    for i in range(len(population)):
        for j in range(i + 1, len(population)):  # Efficient pairing: only compare distinct pairs
            if dominates(fitness_values[i], fitness_values[j], objectives):
                dominated_by[j].append(i)
                domination_counts[j] += 1
            elif dominates(fitness_values[j], fitness_values[i], objectives):
                dominated_by[i].append(j)
                domination_counts[i] += 1

    # Identifying non-dominated individuals (Pareto front 1)
    current_set = [i for i, count in enumerate(domination_counts) if count == 0]
    non_dominated_sets.append(current_set)
    
    # Iteratively find subsequent fronts
    front_index = 0
    while front_index < len(non_dominated_sets):
        next_front = []
        for i in non_dominated_sets[front_index]:
            for j in dominated_by[i]:
                domination_counts[j] -= 1
                if domination_counts[j] == 0:
                    next_front.append(j)
        if next_front:  # Only append if not empty
            non_dominated_sets.append(next_front)
        front_index += 1
    
    print(f"Non-dominated sets: {non_dominated_sets}")
    print(f"Domination Count: {domination_counts}")


# Determine dominance relationship
def dominates(individual_a, individual_b, objectives):
    better_in_any = False
    # Check each objective
    for obj in objectives:
        if individual_a[obj] > individual_b[obj]:  # A’s value is less negative
            better_in_any = True
        elif individual_a[obj] < individual_b[obj]:  # B’s value is less negative
            return False  # If B is better in any single objective, A cannot dominate B

    # If A was never worse and at least once better, A dominates B
    return better_in_any