Source code for nubo.test_functions.hartmann

import torch
from nubo.test_functions import TestFunction
from torch import Tensor
from typing import Optional


[docs] class Hartmann3D(TestFunction): r""" 3-dimensional Hartmann function. The 3-dimensional Hartmann function has four local minima and one global minimum :math:`f(\boldsymbol x^*) = -3.86278` at :math:`\boldsymbol x^* = (0.114614, 0.555649, 0.852547)`. It is usually evaluated on the hypercube :math:`\boldsymbol x \in (0, 1)^3`. .. math:: f(\boldsymbol x) = - \sum_{i=1}^4 \alpha_i \exp \left( - \sum_{j=1}^3 A_{ij} (x_j - P_{ij})^2 \right), where .. math:: \alpha = (1.0, 1.2, 3.0, 3.2)^T, .. math:: \boldsymbol A = \begin{pmatrix} 3.0 & 10.0 & 30.0 \\ 0.1 & 10.0 & 35.0 \\ 3.0 & 10.0 & 30.0 \\ 0.1 & 10.0 & 35.0 \end{pmatrix}, .. math:: \text{and } \boldsymbol P = 10^{-4} \begin{pmatrix} 3689 & 1170 & 2673 \\ 4699 & 4387 & 7470 \\ 1091 & 8732 & 5547 \\ 381 & 5743 & 8828 \end{pmatrix}. Attributes ---------- dims : ``int`` Number of input dimensions. noise_std : ``float`` Standard deviation of Gaussian noise. minimise : ``bool`` Minimisation problem if true, maximisation problem if false. bounds : ``torch.Tensor`` (size 2 x `dims`) Bounds of input space. optimum : ``dict`` Contains inputs and output of global maximum. a : ``torch.Tensor`` (size 4 x 1) Function parameters. A : ``torch.Tensor`` (size 4 x 3) Function parameters. P : ``torch.Tensor`` (size 4 x 3) Function parameters. """ def __init__(self, noise_std: Optional[float]=0.0, minimise: Optional[bool]=True) -> None: """ Parameters ---------- noise_std : ``float``, optional Standard deviation of Gaussian noise, default is 0.0. minimise : ``bool``, optional Minimisation problem if true (default), maximisation problem if false. """ self.dims = 3 self.bounds = Tensor([[0.0, ] * self.dims, [1.0, ] * self.dims]) self.optimum = {"inputs": Tensor([[0.114614, 0.555649, 0.852547]]), "ouput": Tensor([[-3.86278]])} self.noise_std = noise_std self.minimise = minimise self.a = Tensor([1.0, 1.2, 3.0, 3.2]) self.A = Tensor([[3.0, 10.0, 30.0], [0.1, 10.0, 35.0], [3.0, 10.0, 30.0], [0.1, 10.0, 35.0]]) self.P = 10**-4 * Tensor([[3689.0, 1170.0, 2673.0], [4699.0, 4387.0, 7470.0], [1091.0, 8732.0, 5547.0], [ 381.0, 5743.0, 8828.0]])
[docs] def eval(self, x: Tensor) -> Tensor: """ Compute output of Hartmann function for some test points `x`. Parameters ---------- x : ``torch.Tensor`` (size n x `dims`) Test points. """ # reformat to allow matrix computation of multiple points n = x.size(0) d = x.size(1) x = torch.reshape(x, (n, 1, d)) # compute output y = -torch.sum(self.a * torch.exp(-torch.sum(self.A * (x - self.P)**2, dim=-1)), dim=-1) # turn into maximisation problem if not self.minimise: y = -y # add noise noise = torch.normal(mean=0, std=self.noise_std, size=y.size()) f = y + noise return f
[docs] class Hartmann6D(TestFunction): r""" 6-dimensional Hartmann function. The 6-dimensional Hartmann function has six local minima and one global minimum :math:`f(\boldsymbol x^*) = -3.32237` at :math:`\boldsymbol x^* = (0.20169, 0.150011, 0.476874, 0.275332, 0.311652, 0.6573)`. It is usually evaluated on the hypercube :math:`\boldsymbol x \in (0, 1)^6`. .. math:: f(\boldsymbol x) = - \sum_{i=1}^4 \alpha_i \exp \left( - \sum_{j=1}^6 A_{ij} (x_j - P_{ij})^2 \right), where .. math:: \alpha = (1.0, 1.2, 3.0, 3.2)^T, .. math:: \boldsymbol A = \begin{pmatrix} 10.00 & 3.00 & 17.00 & 3.50 & 1.70 & 8.00 \\ 0.05 & 10.00 & 17.00 & 0.10 & 8.00 & 14.00 \\ 3.00 & 3.50 & 1.70 & 10.00 & 17.00 & 8.00 \\ 17.00 & 8.00 & 0.05 & 10.00 & 0.10 & 14.00 \end{pmatrix}, .. math:: \text{and } \boldsymbol P = 10^{-4} \begin{pmatrix} 1312 & 1696 & 5569 & 124 & 8283 & 5886 \\ 2329 & 4135 & 8307 & 3736 & 1004 & 9991 \\ 2348 & 1451 & 3522 & 2883 & 3047 & 6650 \\ 4047 & 8828 & 8732 & 5743 & 1091 & 381 \end{pmatrix}. Attributes ---------- dims : ``int`` Number of input dimensions. noise_std : ``float`` Standard deviation of Gaussian noise. minimise : ``bool`` Minimisation problem if true, maximisation problem if false. bounds : ``torch.Tensor`` (size 2 x `dims`) Bounds of input space. optimum : ``dict`` Contains inputs and output of global maximum. a : ``torch.Tensor`` (size 4 x 1) Function parameters. A : ``torch.Tensor`` (size 4 x 6) Function parameters. P : ``torch.Tensor`` (size 4 x 6) Function parameters. """ def __init__(self, noise_std: Optional[float]=0.0, minimise: Optional[bool]=True) -> None: """ Parameters ---------- noise_std : ``float``, optional Standard deviation of Gaussian noise, default is 0.0. minimise : ``bool``, optional Minimisation problem if true (default), maximisation problem if false. """ self.dims = 6 self.bounds = Tensor([[0.0, ] * self.dims, [1.0, ] * self.dims]) self.optimum = {"inputs": Tensor([[0.20169, 0.150011, 0.476874, 0.275332, 0.311652, 0.6573]]), "ouput": Tensor([[-3.32237]])} self.noise_std = noise_std self.minimise = minimise self.a = Tensor([1.0, 1.2, 3.0, 3.2]) self.A = Tensor([[10.0, 3.0, 17.0, 3.5, 1.7, 8.0], [0.05, 10.0, 17.0, 0.1, 8.0, 14.0], [ 3.0, 3.5, 1.7, 10.0, 17.0, 8.0], [17.0, 8.0, 0.05, 10.0, 0.1, 14.0]]) self.P = 0.0001 * Tensor([[1312.0, 1696.0, 5569.0, 124.0, 8283.0, 5886.0], [2329.0, 4135.0, 8307.0, 3736.0, 1004.0, 9991.0], [2348.0, 1451.0, 3522.0, 2883.0, 3047.0, 6650.0], [4047.0, 8828.0, 8732.0, 5743.0, 1091.0, 381.0]])
[docs] def eval(self, x: Tensor) -> Tensor: """ Compute output of Hartmann function for some test points `x`. Parameters ---------- x : ``torch.Tensor`` (size n x `dims`) Test points. """ # reformat to allow matrix computation of multiple points n = x.size(0) d = x.size(1) x = torch.reshape(x, (n, 1, d)) # compute output y = -torch.sum(self.a * torch.exp(-torch.sum(self.A * (x - self.P)**2, dim=-1)), dim=-1) # turn into maximisation problem if not self.minimise: y = -y # add noise noise = torch.normal(mean=0, std=self.noise_std, size=y.size()) f = y + noise return f