Constrained Optimization Example
This script demonstrates the optimization of a constrained problem using Multi-Objective Bayesian Optimization.
It leverages the QPOTS framework to optimize the Disc Brake problem, a multi-objective problem with constraints.
Overview
Uses BoTorch and PyTorch for Gaussian Process (GP) modeling.
Implements Pareto Optimal Thompson Sampling (QPOTS) for optimization.
Evaluates hypervolume (HV) to measure performance.
Saves results (candidates, hypervolume, and timing) for post-analysis.
Script Details
constrained_optimization.py
1"""
2This file demonstrates an optimization of a constrained problem
3"""
4
5import warnings
6import time
7import os
8import numpy as np
9
10warnings.filterwarnings('ignore')
11
12from qpots.acquisition import Acquisition
13from qpots.model_object import ModelObject
14from qpots.utils.utils import expected_hypervolume
15from qpots.function import Function
16
17import torch
18from botorch.utils.transforms import unnormalize, normalize
19
20device = torch.device("cpu")
21args = dict(
22 {
23 "ntrain": 40,
24 "iters": 200,
25 "reps": 20,
26 "q": 1,
27 "wd": ".",
28 "ref_point": -1*torch.tensor([5.8, 4.0]),
29 "dim": 4,
30 "nobj": 2,
31 "ncons": 4,
32 "nystrom": 0,
33 "nychoice": "pareto",
34 "ngen": 10,
35 }
36 )
37
38tf = Function('discbrake', dim=args["dim"], nobj=args["nobj"])
39f = tf.evaluate
40bounds = tf.get_bounds()
41cons = tf.get_cons()
42
43os.makedirs(args["wd"], exist_ok=True)
44torch.manual_seed(1023)
45
46train_x = torch.rand([args["ntrain"], args["dim"]], dtype=torch.double)
47train_y = f(unnormalize(train_x, bounds))
48train_y = torch.column_stack([train_y, cons(unnormalize(train_x, bounds))]) # Stack constraints on top of objectives
49
50print(train_y.shape, train_x.shape) # This should be n_train x (nobj + ncons) tensor
51
52gps = ModelObject(train_x=train_x, train_y=train_y, bounds=bounds, nobj=args["nobj"], ncons=args["ncons"], device=device)
53gps.fit_gp()
54
55acq = Acquisition(tf, gps, cons=cons, device=device, q=args["q"])
56
57hvs, times = [], []
58for i in range(args["iters"]):
59 t1 = time.time()
60 newx = acq.qpots(bounds=bounds, iteration=i, **args)
61 t2 = time.time()
62 times.append(t2 - t1)
63
64 newy = f(unnormalize(newx.reshape(-1, args["dim"]), bounds))
65 newconsy = cons(unnormalize(newx.reshape(-1, args["dim"]), bounds))
66 newy = torch.column_stack([newy.reshape(args["q"], args["nobj"]),
67 newconsy.reshape(args["q"], args["ncons"])])
68 hv, _ = expected_hypervolume(gps, ref_point=args['ref_point'])
69 hvs.append(hv)
70
71 print(f"Iteration: {i}, New candidate: {newx}, Time: {t2 - t1}, HV: {hv}")
72
73 train_x = torch.row_stack([train_x, newx.view(-1, args["dim"])])
74 train_y = torch.row_stack([train_y, newy])
75 gps = ModelObject(train_x, train_y, bounds, args["nobj"], args["ncons"], device=device)
76 gps.fit_gp()
77
78 np.save(f"{args["wd"]}/train_x.npy", train_x)
79 np.save(f"{args["wd"]}/train_y.npy", train_y)
80 np.save(f"{args["wd"]}/hv.npy", hvs)
81 np.save(f"{args["wd"]}/times.npy", times)
82
Example Output
Iteration: 0, New candidate: tensor([...]), Time: 0.23s, HV: 107.278
Iteration: 1, New candidate: tensor([...]), Time: 0.19s, HV: 123.899
...
Iteration: 199, New candidate: tensor([...]), Time: 0.30s, HV: 151.326
Usage
Run the script using:
python constrained_example.py
Ensure that dependencies such as BoTorch, PyTorch, and PyMoo are installed.