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

Constrained Optimization - penalty within tell method #1510

Closed
GMbeltrami-Cosmo opened this issue May 16, 2023 · 2 comments
Closed

Constrained Optimization - penalty within tell method #1510

GMbeltrami-Cosmo opened this issue May 16, 2023 · 2 comments

Comments

@GMbeltrami-Cosmo
Copy link

GMbeltrami-Cosmo commented May 16, 2023

I have run some tests and as noted in a previous issue, sometimes the constraint is not taken into consideration in a optimization problem, but with my tests I think i have found a quick hotfix for the problem.

https://drive.google.com/file/d/1tC47DbiA1qYN2m5bZyR_flvflat4Knrc/view?usp=share_link

In this link I show four plots with the same function. The left plots show the result the optimizer gives considering the function (the center is the ideal point except when constrained, which was the case in both simulations). The upper plots show the solution with the modification i am about to discuss and the down plots show the original nevergrad code.

It seems evident for me that the modification has some positive effects on the result given.

For clarification:
function minimized: x1^2+x2^2
constraint applied: max(0, 2-x1)
penalty style = default [1e5, 1, 0.5, 1, 0.5, 1]
algorithms tested: ["NGO", "NGOpt", "NGOptBase", "NGOpt4", "NGOpt8", "NGOpt10",
"NGOpt15", "NGOpt16", "NGOpt36", "NGOpt39", 'AvgMetaRecenteringNoHull', 'HullAvgMetaRecentering', 'HullAvgMetaTuneRecentering', 'MetaRecentering', 'MetaTuneRecentering',
"CMandAS2", "DiscreteDoerrOnePlusOne", "ChoiceBase", "CmaFmin2"]

The solution:
Go to nevergrad/optimzation/base.py
In line the tell method definition, change the lines:

if isinstance(loss, float) and (
self.num_objectives == 1 or self.num_objectives > 1 and not self._no_hypervolume
):
self._update_archive_and_bests(candidate, loss)

    if constraint_violation is not None:
        if penalty_style is not None:
            a, b, c, d, e, f = penalty_style
        else:
            a, b, c, d, e, f = (1e5, 1.0, 0.5, 1.0, 0.5, 1.0)

        violation = float(
            (a + np.sum(np.maximum(loss, 0.0)))
            * ((f + self._num_tell) ** e)
            * (b * np.sum(np.maximum(constraint_violation, 0.0) ** c) ** d)
        )
        loss += violation

to:

    if constraint_violation is not None:
        if penalty_style is not None:
            a, b, c, d, e, f = penalty_style
        else:
            a, b, c, d, e, f = (1e5, 1.0, 0.5, 1.0, 0.5, 1.0)

        violation = float(
            (a + np.sum(np.maximum(loss, 0.0)))
            * ((f + self._num_tell) ** e)
            * (b * np.sum(np.maximum(constraint_violation, 0.0) ** c) ** d)
        )
        loss += violation
        
    if isinstance(loss, float) and (
        self.num_objectives == 1 or self.num_objectives > 1 and not self._no_hypervolume
    ):
        self._update_archive_and_bests(candidate, loss)

basically inverting the order of these operations seems to resolve the problem without damaging other functionalities.

@teytaud
Copy link
Contributor

teytaud commented Sep 19, 2023

Pull request for this just now.
Makes sense.

@teytaud
Copy link
Contributor

teytaud commented Sep 19, 2023

0.13.0 merged. Issue presumably solved.

@teytaud teytaud closed this as completed Sep 19, 2023
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