Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pareto front solutions #313

Open
LisieP opened this issue Jan 20, 2025 · 2 comments
Open

Pareto front solutions #313

LisieP opened this issue Jan 20, 2025 · 2 comments

Comments

@LisieP
Copy link

LisieP commented Jan 20, 2025

Hi there,

I'm using the multi-objective pygad implementation with parent_selection_type='nsga2'. I'm interested in the pareto optimal solutions. I can easily plot and extract the fitness values on the pareto front, but how to I access the solutions that are related to the pareto optimal fitness values. For example, if my pareto front plot looks like this:

Image

how do I index the solutions (genes) that correspond to the pareto fitness values?

Kind regards,
Lise

@ahmedfgad
Copy link
Owner

You can use the pareto_fronts property.

ga_inst = pygad.GA(..., parent_selection_type='nsga2')

ga_inst.pareto_fronts

@LisieP
Copy link
Author

LisieP commented Jan 21, 2025

Yes, this is what I did. To give some context, I'm interested in finding the weights for capacity allocation to wind farms. If the generation of each farm is represented by $w_i$, the GA must find the optimal weights, $x_i$ to meet some multi-objective function on the total generation. The total wind generation is expressed as

$$ W_{gen} = \sum^{i}w_i \times x_i $$ where $$ \sum^{i} x_i \leq 1 $$

So when I access the pareto fronts using
ga_inst.pareto_fronts

I get an array of the pareto front fitness values:
array([[0, array([-1.27360746e+08, -3.72970936e+03])], [1, array([-1.27360746e+08, -3.72970936e+03])], [3, array([-1.26405006e+08, -3.73510505e+03])], [8, array([-1.25557120e+08, -3.73989184e+03])], [14, array([-1.24510645e+08, -3.74579978e+03])])

where I'm interested in the weights, $x_i$, that correspond to the pareto front fitness values. Also, my two objectives have significantly different scales, will this influence the chosen optimal solution?

Also- follow up question, the way I ensure that $\sum^{i} x_i \leq 1$ is by applying a large penalty in the fitness function when the sum of the weights exceed one. Is there another work around for constraints in which variables are related to one another? For example I could scale the weights in the on_mutation() callback to force all the solutions in the new generation to adhere to the constraint. This is what I've come up with:

I have a helper function called apply_constraints() which applies the sum constraint to a solution similar to this. So my on_mutation() function looks like this:

def on_mutation(self, ga_instance,offspring_mutation):   
        new_pop = []
        for sol in ga_instance.population:
            solution = self.apply_constraints(sol)
            new_pop.append(solution)
        
        ga_instance.population = np.array(new_pop)

when the fitness of each solution is calculated as:

def fitness_func(self, ga_instance, solution, solution_idx):
        wind_weights = solution[:self.n_farms]
        penalty = 0 
        # make sure sum of weights is leq 1
        if (wind_weights.sum() > 1.0001 ):
            penalty = 10000000000
            print("penalty in solution in generation ", ga_instance.generations_completed , " solution ", solution_idx , "sum is ", wind_weights.sum())

I still get solutions that violate the constraints, also, I get many instances of solution_idx = None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants