## 2 Optimization Problems  
In this section, we define the concept of an optimization problem in a general enough way to include the different types of problems presented in the continuation. Formally, an optimization problem is a pair of objects \((S,\ f)\), where \(S\) is the set of all possible solutions, also known as the search space; and \(f:\ S\rightarrow\mathbb{R}\) is a mapping between \(S\) and the set of real numbers \(\mathbb{R}\), commonly known as the fitness function. An optimization problem can be either a minimization or a maximization problem, and it is completely characterized by the respective instances [14; 15]. Given the definition provided above, we have conceptualized an abstract class, called _Problem_, with the following instance attributes:  
* The search space \(S\), materialized as a dictionary called _space_, holds problem-specific information, such as a problem's dimensionality and spatial bounds;
* The fitness function \(f\), materialized as a function called _function_, calculates the fitness of the proposed solutions;
* An indication regarding optimization's purpose whether it is a minimization or a maximization materialized as a Boolean variable called \(min\_\). Note that \(S\) is highly dependent on the problem type, which is reason why, within this library, it is defined as a dictionary of varied (problem-specific) key-value pairs; when describing different problems in detail, it will be detailed accordingly. Given that \(f\) is an intrinsic characteristic (attribute) of a problem, the solution's fitness evaluation is performed by the respective instances of the problem by means of the following instance methods:  
* **evaluate_sol** evaluates individual candidate solutions (objects of type _Solution_) and is dedicated to single-point metaheuristics;
* **evaluate_pop** evaluates a set of candidate solutions (objects of type _Population_) and is dedicated to population-based metaheuristics. At this stage, it is necessary to justify the existence of two instance methods for the candidate solution's evaluation. As this library accommodates the single-point and population-based metaheuristics, we decided to provide a possibility of efficiently evaluating a set of candidate solutions at a time. In this sense, **evaluate_pop** is designed to encapsulate possible optimization procedures, such as parallel processing. The optimization problems can be classified as \"constrained\" if they impose explicit constraints on the search space \(S\), regardless of any implicit constraint incorporated as penalty term(s) in the fitness function. Assuming that the constraints of a problem are intrinsic characteristics of \(S\), the only object that becomes semantically capable of verifying solution's feasibility is, once again, the problem's instance. The proposed library supports constrained problems by attributing _Problem_ with two instance methods that verify solution's feasibility. * _is_feasible_sol verifies if an individual candidate solution (an object of type _Solution_) satisfies the constraints imposed by \(S\) (dedicated to single-point metaheuristics). The method returns _True_ if the solution is feasible; _False_ otherwise. * _is_feasible_pop_ verifies if a set of candidate solutions (an object of type _Population_) satisfies the constraints imposed by \(S\) (dedicated to population-based metaheuristics). The method returns a tensor of Boolean values, where _True_ represents that a given solution is feasible; _False_ otherwise. In the current release, the algorithms' implementation promotes the convergence without the use of a penalty function (which can be defined as a linear combination of the objective function and some measure of the constraint violation). Instead, a \"minimalistic approach\" is used: the unfeasible solutions automatically receive \"very bad\" fitness--the highest possible value, in the case of a minimization problem; the smallest otherwise.