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

Refactor class Problem #156

Closed
ajnebro opened this issue Dec 7, 2022 · 0 comments
Closed

Refactor class Problem #156

ajnebro opened this issue Dec 7, 2022 · 0 comments
Assignees

Comments

@ajnebro
Copy link
Contributor

ajnebro commented Dec 7, 2022

Class Problem in jMetalPy has the following constructor:

    def __init__(self):
        self.number_of_variables: int = 0
        self.number_of_objectives: int = 0
        self.number_of_constraints: int = 0

        self.reference_front: List[S] = []

        self.directions: List[int] = []
        self.labels: List[str] = []

Several points can be pointed out here:

  1. Setting the number of variables, objectives and constraints should be made with methods instead of state variables.
  2. The reference front is not known for real-world problems and it is used mainly for plotting and for calculating quality indicatores. It does not make sense that it has to be part of a problem.
  3. The directions is used to indicate whether the objective functions are to be minimized or maximized, which is used for generating output results. However, jMetalPy assumes that all the objectives are to be minimized, so this field can bring confusion to users.

The proposal to deal with these issues is to redefine the constructor as follows:

    def __init__(self):
        self.directions: List[int] = []
        self.labels: List[str] = []

    @abstractmethod
    def number_of_variables(self) -> int:
        pass

    @abstractmethod
    def number_of_objectives(self) -> int:
        pass

    @abstractmethod
    def number_of_constraints(self) -> int:
        pass

This way, the FloatProblem class can be implemented in this way:

    def __init__(self):
        super(FloatProblem, self).__init__()
        self.lower_bound = []
        self.upper_bound = []

    def number_of_variables(self) -> int:
        return len(self.lower_bound)

So the unconstrained benchmark problem Kursawecan be defined as:

class Kursawe(FloatProblem):
    """Class representing problem Kursawe."""

    def __init__(self, number_of_variables: int = 3):
        super(Kursawe, self).__init__()

        self.obj_directions = [self.MINIMIZE, self.MINIMIZE]
        self.obj_labels = ["f(x)", "f(y)"]

        self.lower_bound = [-5.0 for _ in range(number_of_variables)]
        self.upper_bound = [5.0 for _ in range(number_of_variables)]

        FloatSolution.lower_bound = self.lower_bound
        FloatSolution.upper_bound = self.upper_bound

    def number_of_objectives(self) -> int:
        return 2

    def number_of_constraints(self) -> int:
        return 0

In the case of the constrained problem Srinivas, it can defined in this way:

class Srinivas(FloatProblem):
    """Class representing problem Srinivas."""

    def __init__(self):
        super(Srinivas, self).__init__()
        number_of_variables = 2

        self.obj_directions = [self.MINIMIZE, self.MINIMIZE]
        self.obj_labels = ["f(x)", "f(y)"]

        self.lower_bound = [-20.0 for _ in range(number_of_variables)]
        self.upper_bound = [20.0 for _ in range(number_of_variables)]

    def number_of_objectives(self) -> int:
        return 2

    def number_of_constraints(self) -> int:
        return 2

    def evaluate(self, solution: FloatSolution) -> FloatSolution:
        x1 = solution.variables[0]
        x2 = solution.variables[1]

        solution.objectives[0] = 2.0 + (x1 - 2.0) * (x1 - 2.0) + (x2 - 1.0) * (x2 - 1.0)
        solution.objectives[1] = 9.0 * x1 - (x2 - 1.0) * (x2 - 1.0)

        self.__evaluate_constraints(solution)

        return solution

About the reference_front and directions state variables, the suggestion is to remove the first one while the second one should be properly documented.

@ajnebro ajnebro self-assigned this Dec 7, 2022
@ajnebro ajnebro closed this as completed Aug 26, 2024
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

1 participant