jMetal / jMetalPy

A framework for single/multi-objective optimization with metaheuristics
https://jmetal.github.io/jMetalPy/index.html
MIT License
498 stars 150 forks source link

Advice on Dynamic Number of Variables #43

Closed milagoranova closed 4 years ago

milagoranova commented 4 years ago

Hi,

I am working on a model where each time a problem is created the number of variables in the solution is different and the solutions in the VAR file should have different length.

Previously, I implemented it where I set the number_of_variables = 1, however that only applied the mutation and crossover from the NSGAII on the first variable of my solution which makes perfect sense.

I am currently implementing a Dynamic NSGAII where during the update() in the problem I update the number of variables and the problem_modified. I am still struggling to implement the stopping condition - I have added the TimeCounter in the main, but not sure if I need to add a time element anywhere in the problem.

Also, please let me know if there is a better way of implementing this.

Thank you in advance for your help.

Kind regards, Mila

benhid commented 4 years ago

Hello Mila,

If I understand you correctly, the idea is to change the number of variables of the problem (and thus, the number of variables of the solutions) each time a problem is created (i.e., before the execution of the algorithm). If so, that parameter can be setted on the constructor of the problem as follows:

from jmetal.problem import ZDT1
problem = ZDT1(number_of_variables=12)

Let me know if it helps (I am not quite sure I'm understanding you).

Regards, Antonio.

milagoranova commented 4 years ago

Hi Antonio,

Apologies for the vague description.

My solution is a vector that has a length between 3 and 10 that is decided on using a random generator. For each run of the problem, each of the solutions in the VAR should have different lengths. Example VAR file with population_size 10: 30 4 16 7 13 1 0 18 6 5 33 0 17 7 6 21 0 15 2 7 11 55 32 13 25 25 5 2 1 0 0 0 0 0 0 1 7 6 0 0 45 26 12 17 25 21 19 9 20 22 0 54 53 10 0 9 2 1 1 0 42 5 23 9 20 16 9 0 0 11 0 0 2 0 0 43 15 8 1 0 0 55 36 38 10 3 6 0 1 0 0 6 54 19 10 4 5 0 0 0

So when number_of_variables = random.randint(3, 10) is used that number is set for all of the solutions. I was looking for a way that each time a new solution is created for that number to change.

Hope this makes my query easier to understand and thanks for your help again.

Kind regards, Mila

benhid commented 4 years ago

Hello Mia,

If I understand properly, the idea is to update the number of variables of the problem (and thus, the number of variables of solutions) on every step of the algorithm.

You can achieve this by, for example, replacing the update method on the algorithm, e.g.:

    def update_progress(self) -> None:
        super().update_progress()
        self.problem.number_of_variables = random.randint(3, 10)

Take into account that solutions are usually created on the initial phase of the algorithm, so this change will have no effect after that point. Furthermore, although some operators take the number of variables from the solutions itselfs, compatibility issues can arise when taking this attribute from the problem (as solution.number_of_variables is not equals to problem.number_of_variables). Also, crossover operators are not devised for solutions with different number of variables.

P.S.: In dynamic algorithms (like the aforementioned) you can replace the restart() strategy:

    def restart(self):
        self.solutions = self.evaluate(self.solutions)

Thank you!

Regards, Antonio.