task2
This commit is contained in:
147
task2/common/functions.py
Normal file
147
task2/common/functions.py
Normal file
@@ -0,0 +1,147 @@
|
||||
"""Function definitions with their gradients for optimization."""
|
||||
|
||||
import math
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Tuple
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
class Function1D(ABC):
|
||||
"""Abstract base class for 1D functions."""
|
||||
|
||||
name: str = "Abstract 1D Function"
|
||||
|
||||
@abstractmethod
|
||||
def __call__(self, x: float) -> float:
|
||||
"""Evaluate function at x."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def gradient(self, x: float) -> float:
|
||||
"""Compute gradient (derivative) at x."""
|
||||
pass
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def domain(self) -> Tuple[float, float]:
|
||||
"""Return the domain [a, b] for this function."""
|
||||
pass
|
||||
|
||||
|
||||
class Function2D(ABC):
|
||||
"""Abstract base class for 2D functions."""
|
||||
|
||||
name: str = "Abstract 2D Function"
|
||||
|
||||
@abstractmethod
|
||||
def __call__(self, x: np.ndarray) -> float:
|
||||
"""Evaluate function at point x = [x1, x2]."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def gradient(self, x: np.ndarray) -> np.ndarray:
|
||||
"""Compute gradient at point x = [x1, x2]."""
|
||||
pass
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def plot_bounds(self) -> Tuple[Tuple[float, float], Tuple[float, float]]:
|
||||
"""Return bounds ((x1_min, x1_max), (x2_min, x2_max)) for plotting."""
|
||||
pass
|
||||
|
||||
|
||||
class TaskFunction1D(Function1D):
|
||||
"""
|
||||
f(x) = sqrt(x^2 + 9) / 4 + (5 - x) / 5
|
||||
|
||||
Derivative: f'(x) = x / (4 * sqrt(x^2 + 9)) - 1/5
|
||||
"""
|
||||
|
||||
name = "f(x) = √(x² + 9)/4 + (5 - x)/5"
|
||||
|
||||
def __call__(self, x: float) -> float:
|
||||
return math.sqrt(x**2 + 9) / 4 + (5 - x) / 5
|
||||
|
||||
def gradient(self, x: float) -> float:
|
||||
return x / (4 * math.sqrt(x**2 + 9)) - 1 / 5
|
||||
|
||||
@property
|
||||
def domain(self) -> Tuple[float, float]:
|
||||
return (-3.0, 8.0)
|
||||
|
||||
|
||||
class HimmelblauFunction(Function2D):
|
||||
"""
|
||||
Himmelblau's function:
|
||||
f(x, y) = (x^2 + y - 11)^2 + (x + y^2 - 7)^2
|
||||
|
||||
Has 4 identical local minima at:
|
||||
- (3.0, 2.0)
|
||||
- (-2.805118, 3.131312)
|
||||
- (-3.779310, -3.283186)
|
||||
- (3.584428, -1.848126)
|
||||
|
||||
Gradient:
|
||||
∂f/∂x = 4x(x² + y - 11) + 2(x + y² - 7)
|
||||
∂f/∂y = 2(x² + y - 11) + 4y(x + y² - 7)
|
||||
"""
|
||||
|
||||
name = "Himmelblau: (x² + y - 11)² + (x + y² - 7)²"
|
||||
|
||||
def __call__(self, x: np.ndarray) -> float:
|
||||
x1, x2 = x[0], x[1]
|
||||
return (x1**2 + x2 - 11) ** 2 + (x1 + x2**2 - 7) ** 2
|
||||
|
||||
def gradient(self, x: np.ndarray) -> np.ndarray:
|
||||
x1, x2 = x[0], x[1]
|
||||
df_dx1 = 4 * x1 * (x1**2 + x2 - 11) + 2 * (x1 + x2**2 - 7)
|
||||
df_dx2 = 2 * (x1**2 + x2 - 11) + 4 * x2 * (x1 + x2**2 - 7)
|
||||
return np.array([df_dx1, df_dx2])
|
||||
|
||||
@property
|
||||
def plot_bounds(self) -> Tuple[Tuple[float, float], Tuple[float, float]]:
|
||||
return ((-5.0, 5.0), (-5.0, 5.0))
|
||||
|
||||
|
||||
class RavineFunction(Function2D):
|
||||
"""
|
||||
Овражная функция (эллиптический параболоид):
|
||||
f(x, y) = x² + 20y²
|
||||
|
||||
Минимум в (0, 0), f(0,0) = 0
|
||||
|
||||
Демонстрирует "эффект оврага" - градиент почти перпендикулярен
|
||||
направлению к минимуму, что замедляет сходимость.
|
||||
|
||||
Gradient:
|
||||
∂f/∂x = 2x
|
||||
∂f/∂y = 40y
|
||||
"""
|
||||
|
||||
name = "Овраг: f(x,y) = x² + 20y²"
|
||||
|
||||
def __call__(self, x: np.ndarray) -> float:
|
||||
x1, x2 = x[0], x[1]
|
||||
return x1**2 + 20 * x2**2
|
||||
|
||||
def gradient(self, x: np.ndarray) -> np.ndarray:
|
||||
x1, x2 = x[0], x[1]
|
||||
df_dx1 = 2 * x1
|
||||
df_dx2 = 40 * x2
|
||||
return np.array([df_dx1, df_dx2])
|
||||
|
||||
@property
|
||||
def plot_bounds(self) -> Tuple[Tuple[float, float], Tuple[float, float]]:
|
||||
return ((-2.0, 2.0), (-0.5, 0.5))
|
||||
|
||||
|
||||
# Registry of available functions
|
||||
FUNCTIONS_1D = {
|
||||
"task": TaskFunction1D,
|
||||
}
|
||||
|
||||
FUNCTIONS_2D = {
|
||||
"himmelblau": HimmelblauFunction,
|
||||
"ravine": RavineFunction,
|
||||
}
|
||||
Reference in New Issue
Block a user