Add necessary utils

This commit is contained in:
Peter Vacho 2025-03-11 01:02:41 +01:00
parent 1bbd75a87b
commit bcf22269e8
Signed by: school
GPG key ID: 8CFC3837052871B4
3 changed files with 162 additions and 0 deletions

42
src/function.py Normal file
View file

@ -0,0 +1,42 @@
from collections.abc import Callable
from dataclasses import dataclass
from typing import NamedTuple
import numpy as np
from src.types import INPUT_VECTOR
class Interval(NamedTuple):
"""Interval determining a number range (both inclusive)."""
min: float
max: float
def random_point(self, dimensions: int, rng: np.random.Generator | None = None) -> INPUT_VECTOR:
"""Generate an N-dimensional random point, where all numbers lie within this interval.
Args:
dimensions: The amount of dimensions this point should have.
rng: Random generator instance (None for a new rng).
"""
if rng is None:
rng = np.random.default_rng()
return rng.uniform(self.min, self.max, size=dimensions)
@dataclass
class Function:
"""Class representing an N-dimensional function.
This function can work with arbitrary number of dimensions, where each input dimension is restricted
within the specified definition interval.
"""
function: Callable[[INPUT_VECTOR], float]
definition_interval: Interval
def __call__(self, params: INPUT_VECTOR) -> float:
"""Evaluate the function."""
return self.function(params)

116
src/functions.py Normal file
View file

@ -0,0 +1,116 @@
"""Various N-dimensional well-known optimization functions.
All of the functions here work with N (# of dimensions) ranging from 1 to infinity.
"""
import numpy as np
from src.function import Function, Interval
from src.types import INPUT_VECTOR
def _sphere_function(vector: INPUT_VECTOR) -> float:
"""Compute the sphere function.
Arguments:
vector: An n-dimensional input vector.
Returns:
float: The function value at the given input vector.
See: https://www.sfu.ca/~ssurjano/spheref.html
"""
return np.sum(vector**2)
sphere_function = Function(_sphere_function, Interval(-10, 10))
def _zakharov_function(vector: INPUT_VECTOR) -> float:
"""Compute the Zakharov function.
Arguments:
vector: An n-dimensional input vector.
Returns:
float: The function value at the given input vector.
See: https://www.sfu.ca/~ssurjano/zakharov.html
"""
d = vector.shape[0]
# First term: sum(x_i^2)
term_1 = np.sum(vector**2)
# Second term: (sum(0.5 * i * x_i))^2
term_2 = np.sum(0.5 * np.arange(1, d + 1) * vector) ** 2
# Third term: (sum(0.5 * i * x_i))^4
term_3 = np.sum(0.5 * np.arange(1, d + 1) * vector) ** 4
return term_1 + term_2 + term_3
zakharov_function = Function(_zakharov_function, Interval(-10, 10))
def _rosenbrock_function(vector: INPUT_VECTOR) -> float:
"""Compute the Rosenbrock function.
Arguments:
vector: An n-dimensional input vector.
Returns:
float: The function value at the given input vector.
See: https://www.sfu.ca/~ssurjano/rosenbrockf.html
"""
return np.sum(100 * (vector[:-1] ** 2 - vector[1:]) ** 2 + (1 - vector[:-1]) ** 2)
rosenbrock_function = Function(_rosenbrock_function, Interval(-10, 10))
def _schwefel_function(vector: INPUT_VECTOR) -> float:
"""Compute the Schwefel function.
Arguments:
vector: An n-dimensional input vector.
Returns:
float: The function value at the given input vector.
See: https://www.sfu.ca/~ssurjano/schwefel.html
"""
d = vector.shape[0]
return 418.9829 * d - np.sum(vector * np.sin(np.sqrt(np.abs(vector))))
schwefel_function = Function(_schwefel_function, Interval(-500, 500))
def _styblinski_tang_function(vector: INPUT_VECTOR) -> float:
"""Compute the Styblinski-Tang function.
Arguments:
vector: An n-dimensional input vector.
Returns:
float: The function value at the given input vector.
See: https://www.sfu.ca/~ssurjano/stybtang.html
"""
return 0.5 * np.sum(vector**4 - 16 * vector**2 + 5 * vector)
styblinski_tang_function = Function(_styblinski_tang_function, Interval(-5, 5))
available_functions = {
"Sphere": sphere_function,
"Zakharov": zakharov_function,
"Rosenbrock": rosenbrock_function,
"Schwefel": schwefel_function,
"Styblinski-Tang": styblinski_tang_function,
}

4
src/types.py Normal file
View file

@ -0,0 +1,4 @@
import numpy as np
import numpy.typing as npt
type INPUT_VECTOR = npt.NDArray[np.float64]