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

Expected an unbounded problem, but this problem has lower and/or upper bounds. #114

Open
turian opened this issue Aug 16, 2024 · 1 comment

Comments

@turian
Copy link

turian commented Aug 16, 2024

I have a bounded problem, I tried both PGPE and CMAES but I get the error:

Expected an unbounded problem, but this problem has lower and/or upper bounds.

Is there any solver for bounded problems?

@engintoklu
Copy link
Collaborator

Hello turian,

Thank you for your question, and for trying out EvoTorch!

These algorithms support bounded problems:

Distribution-based search algorithm implementations of EvoTorch such as PGPE and CMAES do not support strictly bounded problems. Still, you could define initial_bounds, and then augment your fitness function by adding penalty terms to discourage the exploration of the infeasible regions.

I think such an augmented problem definition could look like this (I hope it works and/or helps, feel free to let me know):

import torch
from evotorch import Problem, SolutionBatch


class MyBoundedProblem(Problem):
    ...

    def _evaluate_batch(self, batch: SolutionBatch):
        # Take the decision values from the solution batch
        values = batch.values

        # identify where the lower and upper bounds are violated within the batch
        lb_violated = values < self.lower_bounds
        ub_violated = values > self.upper_bounds

        # for each solution within the batch, compute the total amount of violation
        violation_amounts = (
            torch.where(lb_violated, self.lower_bounds - values, 0.0)
            + torch.where(ub_violated, values - self.upper_bounds, 0.0)
        ).sum(dim=-1)

        # get the clipped counterpart of the values, such that the boundaries are not
        # violated anymore
        clipped_values = torch.where(lb_violated, self.lower_bounds, values)
        clipped_values = torch.where(ub_violated, self.upper_bounds, clipped_values)

        # compute the fitnesses (or solution costs) using the clipped decision values
        fitnesses = SomehowComputeTheFitnesses(clipped_values)

        penalty_sign = 1.0 if self.objective_sense == "min" else -1.0

        # the magnitude of the penalty is 100 times the violation squared
        # (needs tuning according to the fitness scale of the problem at hand)
        penalties = penalty_sign * 100.0 * (violation_amounts ** 2)

        # Evaluations take into account fitnesses and the penalties
        batch.set_evals(fitnesses + penalties)

EvoTorch also introduced helper functions for detecting the amount of violations for constraints, and for penalizing them (using exponential penalization or using log barriers), but they have not been included in a release yet: https://github.com/nnaisense/evotorch/blob/master/src/evotorch/tools/constraints.py.
If you are okay with installing EvoTorch directly from its master branch on GitHub, you could also use these helper functions, if you prefer.

Feel free to let us know if you have further questions, or if something is not clear.

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