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

The repair is not passed to the mating argument of the MixedVariableGA class #575

Open
xinwang0312 opened this issue Mar 8, 2024 · 5 comments
Assignees

Comments

@xinwang0312
Copy link

Not sure whether this is by design, suppose I want to have a customized repair for MixedVariableGA. But this customized repair is not passed to the mating argument

mating=MixedVariableMating(eliminate_duplicates=MixedVariableDuplicateElimination()),

As a consequence, the mated population may not follow the constraints defined in the customized repair unless it is specifically passed such as

mating=MixedVariableMating(eliminate_duplicates=MixedVariableDuplicateElimination(), repair=some_repair())

@blankjul blankjul self-assigned this Mar 16, 2024
@blankjul
Copy link
Collaborator

Without having tried it myself, repair is a paramter of MixedVariableMating. Can you check if passing it here works for you?

@xinwang0312
Copy link
Author

@blankjul Yes, actually it is what I mean and it took me sometime to figure out. The customized repair not only has to be passed for the MixedVariableGA itself, but also has to be explicitly passed to MixedVariableMating.

So the initialization of a MixedVariableGA with a customized repaire would be something like below, which is not very handy to use.

algo = MixedVariableGA(
    ..., 
    mating=MixedVariableMating(eliminate_duplicates=MixedVariableDuplicateElimination(), repair=some_repair()),
    repair=some_repair()
   )

If it is not by design, maybe we can consider to first check whether repair is in the kwargs, if it is, then also "add" it to the mating?

@blankjul
Copy link
Collaborator

This actually is by design. The main reason is that the mating creates n individuals which are not duplicated with the population passed AND within itself. To determine if an indvidual is a duplicate we first have to run the Repair operator. Otherwise, it might not be a duplicate initially, but then become one after the repair operator has been applied.

I was thinking about this statement

The customized repair not only has to be passed for the MixedVariableGA itself, but also has to be explicitly passed to MixedVariableMating.

Does this imply if you DO NOT pass it to MixedVariableGA it does not work? I would think ONLY passing it to MixedVariableMating should be sufficient. Can you quickly check if this is the case?

@xinwang0312
Copy link
Author

Hi @blankjul , sorry for the late reply. No, only passing the repair to the mating does not work. I have a minimum working example based on https://pymoo.org/customization/mixed.html to reproduce the test.

My pymoo version is 0.6.1.1.

So I want to apply a simple constraint to force x['b'] + x['y'] + x['z'] = 5

  1. if I only pass the repair to the algorithm, the constraint only holds for the first iteration and then breaks
  2. if I both pass the repair to the algorithm and the mating, the constraint only holds, which is desired
  3. if I only pass the repair to the mating, I got a warning "WARNING: Mating could not produce the required number of (unique) offsprings!"

I hope this is enough for you to reproduce the test and let me know if you need anything else.

from pymoo.core.mixed import (
    MixedVariableDuplicateElimination,
    MixedVariableGA,
    MixedVariableMating,
)
from pymoo.core.problem import ElementwiseProblem
from pymoo.core.repair import Repair
from pymoo.core.variable import Binary, Choice, Integer, Real
from pymoo.optimize import minimize


class MixedVariableProblem(ElementwiseProblem):

    def __init__(self, **kwargs):
        vars = {
            "b": Binary(),
            "x": Choice(options=["nothing", "multiply"]),
            "y": Integer(bounds=(0, 2)),
            "z": Real(bounds=(0, 5)),
        }
        super().__init__(vars=vars, n_obj=1, **kwargs)

    def _evaluate(self, X, out, *args, **kwargs):
        b, x, z, y = X["b"], X["x"], X["z"], X["y"]

        f = z + y
        if b:
            f = 100 * f

        if x == "multiply":
            f = 10 * f

        out["F"] = f


class ToyRepair(Repair):
    def _do(self, problem, X, **kwargs):
        return [self._repair_z(x) for x in X]

    @staticmethod
    def _repair_z(x):
        x["z"] = 5 - x["b"] - x["y"]
        return x


problem = MixedVariableProblem()

# algorithm = MixedVariableGA(pop=10, repair=ToyRepair()) # constraint does not hold
mating = MixedVariableMating(
    eliminate_duplicates=MixedVariableDuplicateElimination(), repair=ToyRepair()
)
# algorithm = MixedVariableGA(
#     pop=10, mating=mating, repair=ToyRepair()
# )  # constraint hold

# WARNING: Mating could not produce the required number of (unique) offsprings!
algorithm = MixedVariableGA(pop=10, mating=mating)


res = minimize(problem, algorithm, termination=("n_evals", 1000), seed=1, verbose=True)

print("Best solution found: \nX = %s\nF = %s" % (res.X, res.F))

@blankjul
Copy link
Collaborator

Fair point! I have just checked the code and can reproduce it!

In fact, not passing it will make the initial population to be non-repaired. But all individuals will be repaired later on!
Do you have any direct suggestion how you would expect this to be improved? Happy to look at a PR as well.

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

No branches or pull requests

2 participants