Skip to content

Commit ec4aca7

Browse files
VilockLifacebook-github-bot
authored andcommitted
Update three augmented test functions for multi-fidelity bayesian optimization; updated _init_.py and branin.py (#168)
Summary: Pull Request resolved: #168 We wrote three augmented test functions for multi-fidelity bayesian optimization from section 5.3 in https://arxiv.org/abs/1903.04703; _init_.py and branin.py were updated as well. Reviewed By: bkarrer Differential Revision: D15614824 fbshipit-source-id: eecc2938a17ce0def811d223c94ab98845cc9334
1 parent a5f2dba commit ec4aca7

File tree

8 files changed

+299
-2
lines changed

8 files changed

+299
-2
lines changed

botorch/test_functions/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
44

5+
from .aug_branin import neg_aug_branin
6+
from .aug_hartmann6 import neg_aug_hartmann6
7+
from .aug_rosenbrock import neg_aug_rosenbrock
58
from .branin import neg_branin
69
from .eggholder import neg_eggholder
710
from .hartmann6 import neg_hartmann6
@@ -17,4 +20,7 @@
1720
"neg_holder_table",
1821
"neg_michalewicz",
1922
"neg_styblinski_tang",
23+
"neg_aug_branin",
24+
"neg_aug_hartmann6",
25+
"neg_aug_rosenbrock",
2026
]
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
4+
5+
import math
6+
7+
import torch
8+
from torch import Tensor
9+
10+
11+
# This function has infinitely many global maximizers
12+
GLOBAL_MAXIMUM = -0.397887
13+
14+
15+
def neg_aug_branin(X: Tensor) -> Tensor:
16+
r"""Negative augmented-Branin test function.
17+
18+
The last dimension of X is the fidelity.
19+
3-dimensional function with domain `[-5, 10] x [0, 15] * [0,1]`:
20+
21+
B(x) = (x_2 - (b - 0.1 * (1 - x_3))x_1^2 + c x_1 - r)^2 +
22+
10 (1-t) cos(x_1) + 10
23+
24+
Here `b`, `c`, `r` and `t` are constants where `b = 5.1 / (4 * math.pi ** 2)`
25+
`c = 5 / math.pi`, `r = 6`, `t = 1 / (8 * math.pi)`.
26+
B has infinitely many minimizers with `x_1 = -pi, pi, 3pi`
27+
28+
and `B_min = 0.397887`
29+
30+
Args:
31+
X: A Tensor of size `3` or `k x 3` (`k` batch evaluations).
32+
33+
Returns:
34+
`-B(X)`, the negative value of the augmented-Branin function.
35+
"""
36+
batch = X.ndimension() > 1
37+
X = X if batch else X.unsqueeze(0)
38+
t1 = (
39+
X[:, 1]
40+
- (5.1 / (4 * math.pi ** 2) - 0.1 * (1 - X[:, 2])) * X[:, 0] ** 2
41+
+ 5 / math.pi * X[:, 0]
42+
- 6
43+
)
44+
t2 = 10 * (1 - 1 / (8 * math.pi)) * torch.cos(X[:, 0])
45+
B = t1 ** 2 + t2 + 10
46+
result = -B
47+
return result if batch else result.squeeze(0)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
4+
5+
import torch
6+
from torch import Tensor
7+
8+
from .hartmann6 import ALPHA, A, P
9+
10+
11+
GLOBAL_MAXIMIZER = [0.20169, 0.150011, 0.476874, 0.275332, 0.311652, 0.6573, 1]
12+
13+
14+
def neg_aug_hartmann6(X: Tensor) -> Tensor:
15+
r"""Negative augmented Hartmann6 test function.
16+
17+
The last dimension of X is the fidelity parameter.
18+
7-dimensional function (typically evaluated on `[0, 1]^7`):
19+
20+
H(x) = -(ALPHA_1 - 0.1 * (1-x_7)) * exp(- sum_{j=1}^6 A_1j (x_j - P_1j) ** 2) -
21+
sum_{i=2}^4 ALPHA_i exp( - sum_{j=1}^6 A_ij (x_j - P_ij) ** 2)
22+
23+
H has unique global minimizer
24+
x = [0.20169, 0.150011, 0.476874, 0.275332, 0.311652, 0.6573, 1]
25+
26+
with `H_min = -3.32237`
27+
28+
Args:
29+
X: A Tensor of size `7` or `k x 7` (k batch evaluations).
30+
31+
Returns:
32+
`-H(X)`, the negative value of the augmented Hartmann6 function.
33+
"""
34+
batch = X.ndimension() > 1
35+
X = X if batch else X.unsqueeze(0)
36+
inner_sum = torch.sum(
37+
X.new(A) * (X[:, :6].unsqueeze(1) - 0.0001 * X.new(P)) ** 2, dim=2
38+
)
39+
alpha1 = ALPHA[0] - 0.1 * (1 - X[:, 6])
40+
H = (
41+
-torch.sum(X.new(ALPHA)[1:] * torch.exp(-inner_sum)[:, 1:], dim=1)
42+
- alpha1 * torch.exp(-inner_sum)[:, 0]
43+
)
44+
result = -H
45+
return result if batch else result.squeeze(0)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
4+
5+
from torch import Tensor
6+
7+
8+
# This function has infinitely many global maximizers.
9+
GLOBAL_MAXIMUM = 0.0
10+
11+
12+
def neg_aug_rosenbrock(X: Tensor):
13+
r"""Augmented Rosenbrock test function.
14+
15+
4-dimensional function, the last two dimensions are for fidelity parameters,
16+
X is usually in [-5,10]^2 * [0,1]^2:
17+
18+
f(x) = 100 (x_2 - x_1^2 + 0.1 * (1 - x_3))^2 + (x_1 - 1 + 0.1 * (1 - x_4)^2)^2
19+
20+
f has infinitely many minimizers, with `f_min = 0.0`
21+
22+
Args:
23+
X: A Tensor of size `4` or `k x 4` (`k` batch evaluations).
24+
Returns:
25+
`-f(X)`, the negative value of the augmented Rosenbrock function.
26+
"""
27+
batch = X.ndimension() > 1
28+
X = X if batch else X.unsqueeze(0)
29+
result = (
30+
-100 * (X[:, 1] - X[:, 0] ** 2 + 0.1 * (1 - X[:, 2])) ** 2
31+
+ (X[:, 0] - 1 + 0.1 * (1 - X[:, 3]) ** 2) ** 2
32+
)
33+
return result if batch else result.squeeze(0)

botorch/test_functions/branin.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ def neg_branin(X: Tensor) -> Tensor:
1717
1818
Two-dimensional function (usually evaluated on `[-5, 10] x [0, 15]`):
1919
20-
`B(x) = (x2 - b x_1^2 + c x_1 - r)^2 + 10 (1-t) cos(x_1) + 10`
20+
`B(x) = (x_2 - b x_1^2 + c x_1 - r)^2 + 10 (1-t) cos(x_1) + 10`
2121
22+
Here `b`, `c`, `r` and `t` are constants where `b = 5.1 / (4 * math.pi ** 2)`
23+
`c = 5 / math.pi`, `r = 6`, `t = 1 / (8 * math.pi)`
2224
B has 3 minimizers for its global minimum at
2325
2426
`z_1 = (-pi, 12.275), z_2 = (pi, 2.275), z_3 = (9.42478, 2.475)`
2527
26-
with `B(z_i) = -0.397887`
28+
with `B(z_i) = 0.397887`
2729
2830
Args:
2931
X: A Tensor of size `2` or `k x 2` (`k` batch evaluations).
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#! /usr/bin/env python3
2+
3+
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
4+
5+
import math
6+
import unittest
7+
8+
import torch
9+
from botorch.test_functions.aug_branin import GLOBAL_MAXIMUM, neg_aug_branin
10+
11+
12+
class TestNegAugBranin(unittest.TestCase):
13+
def test_single_eval_neg_aug_branin(self, cuda=False):
14+
device = torch.device("cuda") if cuda else torch.device("cpu")
15+
for dtype in (torch.float, torch.double):
16+
X = torch.zeros(3, device=device, dtype=dtype)
17+
res = neg_aug_branin(X)
18+
self.assertEqual(res.dtype, dtype)
19+
self.assertEqual(res.device.type, device.type)
20+
self.assertEqual(res.shape, torch.Size())
21+
22+
def test_single_eval_neg_aug_branin_cuda(self):
23+
if torch.cuda.is_available():
24+
self.test_single_eval_neg_aug_branin(cuda=True)
25+
26+
def test_batch_eval_neg_aug_branin(self, cuda=False):
27+
device = torch.device("cuda") if cuda else torch.device("cpu")
28+
for dtype in (torch.float, torch.double):
29+
X = torch.zeros(2, 3, device=device, dtype=dtype)
30+
res = neg_aug_branin(X)
31+
self.assertEqual(res.dtype, dtype)
32+
self.assertEqual(res.device.type, device.type)
33+
self.assertEqual(res.shape, torch.Size([2]))
34+
35+
def test_batch_eval_neg_aug_branin_cuda(self):
36+
if torch.cuda.is_available():
37+
self.test_batch_eval_neg_aug_branin(cuda=True)
38+
39+
def test_neg_aug_branin_global_maxima(self, cuda=False):
40+
device = torch.device("cuda") if cuda else torch.device("cpu")
41+
for dtype in (torch.float, torch.double):
42+
X = torch.tensor(
43+
[
44+
[-math.pi, 12.275, 1],
45+
[math.pi, 1.3867356039019576, 0.1],
46+
[math.pi, 1.781519779945532, 0.5],
47+
[math.pi, 2.1763039559891064, 0.9],
48+
],
49+
device=device,
50+
dtype=dtype,
51+
requires_grad=True,
52+
)
53+
res = neg_aug_branin(X)
54+
for r in res:
55+
self.assertAlmostEqual(r.item(), GLOBAL_MAXIMUM, places=4)
56+
grad = torch.autograd.grad(res.sum(), X)[0]
57+
self.assertLess(grad.abs().max().item(), 1e-4)
58+
59+
def test_neg_aug_branin_global_maxima_cuda(self):
60+
if torch.cuda.is_available():
61+
self.test_neg_aug_branin_global_maxima(cuda=True)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#! /usr/bin/env python3
2+
3+
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
4+
5+
import unittest
6+
7+
import torch
8+
from botorch.test_functions.aug_hartmann6 import GLOBAL_MAXIMIZER, neg_aug_hartmann6
9+
from botorch.test_functions.hartmann6 import GLOBAL_MAXIMUM
10+
11+
12+
class TestNegAugHartmann6(unittest.TestCase):
13+
def test_single_eval_neg_aug_hartmann6(self, cuda=False):
14+
device = torch.device("cuda") if cuda else torch.device("cpu")
15+
for dtype in (torch.float, torch.double):
16+
X = torch.zeros(7, device=device, dtype=dtype)
17+
res = neg_aug_hartmann6(X)
18+
self.assertEqual(res.dtype, dtype)
19+
self.assertEqual(res.device.type, device.type)
20+
self.assertEqual(res.shape, torch.Size())
21+
22+
def test_single_eval_neg_aug_hartmann6_cuda(self):
23+
if torch.cuda.is_available():
24+
self.test_single_eval_neg_aug_hartmann6(cuda=True)
25+
26+
def test_batch_eval_neg_aug_hartmann6(self, cuda=False):
27+
device = torch.device("cuda") if cuda else torch.device("cpu")
28+
for dtype in (torch.float, torch.double):
29+
X = torch.zeros(2, 7, device=device, dtype=dtype)
30+
res = neg_aug_hartmann6(X)
31+
self.assertEqual(res.dtype, dtype)
32+
self.assertEqual(res.device.type, device.type)
33+
self.assertEqual(res.shape, torch.Size([2]))
34+
35+
def test_batch_eval_neg_aug_hartmann6_cuda(self):
36+
if torch.cuda.is_available():
37+
self.test_batch_eval_neg_aug_hartmann6(cuda=True)
38+
39+
def test_neg_aug_hartmann6_global_maximum(self, cuda=False):
40+
device = torch.device("scuda") if cuda else torch.device("cpu")
41+
for dtype in (torch.float, torch.double):
42+
X = torch.tensor(GLOBAL_MAXIMIZER, device=device, dtype=dtype)
43+
res = neg_aug_hartmann6(X)
44+
self.assertAlmostEqual(res.item(), GLOBAL_MAXIMUM, places=4)
45+
46+
def test_neg_aug_hartmann6_global_maximum_cuda(self):
47+
if torch.cuda.is_available():
48+
self.test_neg_aug_hartmann6_global_maximum(cuda=False)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#! /usr/bin/env python3
2+
3+
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
4+
5+
import unittest
6+
7+
import torch
8+
from botorch.test_functions.aug_rosenbrock import GLOBAL_MAXIMUM, neg_aug_rosenbrock
9+
10+
11+
class TestNegAugRosenbrock(unittest.TestCase):
12+
def test_single_eval_neg_aug_rosenbrock(self, cuda=False):
13+
device = torch.device("cuda") if cuda else torch.device("cpu")
14+
for dtype in (torch.float, torch.double):
15+
X = torch.zeros(4, device=device, dtype=dtype)
16+
res = neg_aug_rosenbrock(X)
17+
self.assertEqual(res.dtype, dtype)
18+
self.assertEqual(res.device.type, device.type)
19+
self.assertEqual(res.shape, torch.Size())
20+
21+
def test_single_eval_neg_aug_rosenbrock_cuda(self):
22+
if torch.cuda.is_available():
23+
self.test_single_eval_neg_aug_rosenbrock(cuda=True)
24+
25+
def test_batch_eval_neg_aug_rosenbrock(self, cuda=False):
26+
device = torch.device("cuda") if cuda else torch.device("cpu")
27+
for dtype in (torch.float, torch.double):
28+
X = torch.zeros(2, 4, device=device, dtype=dtype)
29+
res = neg_aug_rosenbrock(X)
30+
self.assertEqual(res.dtype, dtype)
31+
self.assertEqual(res.device.type, device.type)
32+
self.assertEqual(res.shape, torch.Size([2]))
33+
34+
def test_batch_eval_neg_aug_rosenbrock_cuda(self):
35+
if torch.cuda.is_available():
36+
self.test_batch_eval_neg_aug_rosenbrock(cuda=True)
37+
38+
def test_neg_aug_rosenbrock_global_maximum(self, cuda=False):
39+
device = torch.device("cuda") if cuda else torch.device("cpu")
40+
for dtype in (torch.float, torch.double):
41+
X = torch.tensor(
42+
[[1, 1, 1, 1], [1, 0.95, 0.5, 1], [1, 0.91, 0.1, 1], [1, 0.99, 0.9, 1]],
43+
device=device,
44+
dtype=dtype,
45+
requires_grad=True,
46+
)
47+
res = neg_aug_rosenbrock(X)
48+
for r in res:
49+
self.assertAlmostEqual(r.item(), GLOBAL_MAXIMUM, places=4)
50+
grad = torch.autograd.grad(res.sum(), X)[0]
51+
self.assertLess(grad.abs().max().item(), 1e-4)
52+
53+
def test_neg_aug_rosenbrock_global_maximum_cuda(self):
54+
if torch.cuda.is_available():
55+
self.test_neg_aug_rosenbrock_global_maximum(cuda=False)

0 commit comments

Comments
 (0)