"""
Set of constant values used around the library (mostly for internal use) to support its algorithm implementations.
"""
from __future__ import (
annotations,
)
import heapq
import logging
from enum import (
Enum,
unique,
)
from math import (
sqrt,
)
from sys import (
maxsize,
)
from typing import (
TYPE_CHECKING,
)
if TYPE_CHECKING:
from typing import (
Callable,
Iterable,
TypeVar,
List,
Union,
)
T = TypeVar("T")
Number = Union[int, float]
logger = logging.getLogger(__name__)
MAX_INT = maxsize
MIN_INT = -maxsize
MAX_FLOAT = float("inf")
MIN_FLOAT = float("-inf")
ERROR_BOUND = 10e-4
[docs]@unique
class OptimizationDirection(Enum):
MAXIMIZATION = max
MINIMIZATION = min
def __call__(self, *args, **kwargs):
return self.value(*args, **kwargs)
def __str__(self):
return f"{self.name.capitalize()}"
@property
def _reverse(self):
return self.value == max
[docs] def sorted(self, iterable: Iterable[T], key: Callable[[T], float], inplace: bool = False) -> List[T]:
if isinstance(iterable, list) and inplace:
iterable.sort(key=key, reverse=self._reverse)
else:
if inplace:
logger.warning('"inplace" sorting is possible only over list objects.')
iterable = sorted(iterable, key=key, reverse=self._reverse)
return iterable
[docs] def nbest(self, n: int, iterable: Iterable[T], key: Callable[[T], float], inplace: bool = False) -> List[T]:
if self._reverse:
return heapq.nlargest(n, iterable, key=key)
else:
return heapq.nsmallest(n, iterable, key=key)
[docs]@unique
class DistanceMetric(Enum):
@staticmethod
def _euclidean_distance(a: Iterable[Number], b: Iterable[Number]) -> float:
return sqrt(sum(pow(a_i - b_i, 2) for a_i, b_i in zip(a, b)))
@staticmethod
def _manhattan_distance(a: Iterable[Number], b: Iterable[Number]) -> float:
return sum(abs(a_i - b_i) for a_i, b_i in zip(a, b))
EUCLIDEAN = _euclidean_distance
MANHATTAN = _manhattan_distance
def __call__(self, *args, **kwargs):
return self.value(*args, **kwargs)
def __str__(self):
return f"{self.name.capitalize()}"