#!/usr/bin/env python
# Created by "Thieu" at 16:39, 05/05/2023 ----------%
# Email: nguyenthieu2102@gmail.com %
# Github: https://github.com/thieu1995 %
# --------------------------------------------------%
import numpy as np
from abc import ABC
[docs]class Engineer(ABC):
"""
Defines an abstract class for engineering design problems.
All subclasses should implement the ``evaluate`` method for a particular problem.
Attributes
----------
bounds : list
The lower/upper bounds of the problem. This a 2D-matrix of [lower, upper] array that contain the lower and upper bounds.
By default, each problem has its own bounds. But user can try to put different bounds to test the problem.
n_dims : int
The dimensionality of the problem. It is calculated from bounds
lb : np.ndarray
The lower bounds for the problem
ub : np.ndarray
The upper bounds for the problem
f_global : float
The global optimum of the evaluated function.
x_global : np.ndarray
A list of vectors that provide the locations of the global minimum.
Note that some problems have multiple global minima, not all of which may be listed.
n_fe : int
The number of function evaluations that the object has been asked to calculate.
"""
name = "Benchmark name"
linear = False
convex = True
differentiable = True
parametric = True
def __init__(self):
self._bounds = None
self._n_dims = None
self._n_objs = 1
self._n_cons = 0
self._n_ineq_cons = -1
self._n_eq_cons = -1
self.f_penalty = None
self.f_global = None
self.x_global = None
self.n_fe = 0
self.paras = {}
self.epsilon = 1e-8
self.w = 1e8
[docs] def get_objs(self, x):
"""
Compute the values of the objective functions for a given set of input values.
"""
pass
[docs] def get_cons(self, x):
"""
Compute the values of the constraint functions for a given set of input values.
"""
pass
[docs] def get_eq_cons(self, x):
"""
Compute the values of the equality constraint functions for a given set of input values.
"""
pass
[docs] def get_ineq_cons(self, x):
"""
Compute the values of the inequality constraint functions for a given set of input values.
"""
pass
[docs] def get_paras(self):
"""
Return the parameters of the problem. Depended on function
"""
default = {"bounds": self._bounds, "n_dims": self._n_dims, }
return {**default, **self.paras}
@property
def bounds(self):
"""
The lower/upper bounds to be used for optimization problem. This a 2D-matrix of [lower, upper] array that contain the lower and upper
bounds for the problem. The problem should not be asked for evaluation outside these bounds. ``len(bounds) == n_dims``.
"""
return self._bounds
@property
def n_dims(self):
"""
The dimensionality of the problem.
"""
return self._n_dims
@property
def n_objs(self):
"""
The number of objective functions of the problem.
"""
return self._n_objs
@property
def n_cons(self):
"""
The number of constraint functions of the problem.
"""
return self._n_cons
@property
def n_eq_cons(self):
"""
The number of equality constraint functions of the problem.
"""
return self._n_eq_cons
@property
def n_ineq_cons(self):
"""
The number of inequality constraint functions of the problem.
"""
return self._n_ineq_cons
@property
def lb(self):
"""
The lower bounds for the problem
Returns
-------
lb : 1D-vector
The lower bounds for the problem
"""
return np.array([x[0] for x in self.bounds])
@property
def ub(self):
"""
The upper bounds for the problem
Returns
-------
ub : 1D-vector
The upper bounds for the problem
"""
return np.array([x[1] for x in self.bounds])
[docs] def amend_position(self, x, lb=None, ub=None):
"""
Amend position to fit the format of the problem
Parameters
----------
x : np.ndarray
The current position (solution)
"""
return x
[docs] def create_solution(self):
"""
Create a random solution for the current problem
Returns
-------
solution: np.ndarray
The random solution
"""
return np.random.uniform(self.lb, self.ub)
[docs] def check_solution(self, x):
"""
Raise the error if the problem size is not equal to the solution length
Parameters
----------
x : np.ndarray
The solution
"""
if len(x) != self._n_dims:
raise ValueError(f"The length of solution should has {self._n_dims} variables!")
[docs] def default_penalty(self, list_objs=None, list_cons=None):
list_objs_new = np.zeros_like(list_objs)
for idx, val in enumerate(list_objs):
temp = val + self.w * np.sum([max(0, f_con) for f_con in list_cons])
list_objs_new[idx] = temp
return list_objs_new
[docs] def check_penalty_func(self, func=None):
if callable(func):
self.f_penalty = func
else:
self.f_penalty = self.default_penalty
[docs] def evaluate(self, x):
"""
Evaluation of the benchmark function.
Parameters
----------
x : np.ndarray, list, tuple
The candidate vector for evaluating the benchmark problem. Must have ``len(x) == self.n_dims``.
Returns
-------
val : float
the evaluated benchmark function
"""
pass