Unconstrained Example

This example demonstrates how to use qPOTS for multi-objective optimization on the BraninCurrin function from BoTorch. It is a non-HPC implementation designed for local execution.

Overview

  • Optimizes a 2-dimensional, 2-objective problem.

  • Uses Pareto Optimal Thompson Sampling (QPOTS) for acquisition.

  • Evaluates hypervolume (HV) at each step.

  • Saves training data, hypervolume values, and computational times for analysis.

Script Details

botorch_qpots_example.py
 1"""
 2This example demonstrates how to use qPOTS on a BoTorch multiobjective test function called BraninCurrin.
 3This is not an HPC implementation.
 4"""
 5import warnings
 6import os
 7import time
 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
15
16import torch
17from qpots.function import Function
18from botorch.utils.transforms import unnormalize
19
20device = torch.device("cpu")
21args = dict(
22    {
23        "ntrain": 20,
24        "iters": 50,
25        "reps": 20,
26        "q": 1,
27        "wd": ".",
28        "ref_point": torch.tensor([-300.0, -18.0]),
29        "dim": 2,
30        "nobj": 2,
31        "ncons": 0,
32        "nystrom": 0,
33        "nychoice": "pareto",
34        "ngen": 10,
35    }
36)
37
38# Set up problem
39tf = Function('branincurrin', dim=args["dim"], nobj=args["nobj"])
40f = tf.evaluate
41bounds = tf.get_bounds()
42
43os.makedirs(args["wd"], exist_ok=True)
44torch.manual_seed(1023)
45
46# set up the training points
47train_x = torch.rand([args["ntrain"], args["dim"]], dtype=torch.double)
48train_y = f(unnormalize(train_x, bounds))
49
50# fit the GP models
51gps = ModelObject(train_x, train_y, bounds, args["nobj"], args["ncons"], device=device)
52gps.fit_gp()
53
54# initialize 
55acq = Acquisition(tf, gps, device=device, q=args["q"])
56
57times, hvs = [], []
58for i in range(args["iters"]):
59    t1 = time.time() # tracking time
60    newx = acq.qpots(bounds, i, **args)
61    t2 = time.time()
62    times.append(t2 - t1)
63    
64    newy = f(unnormalize(newx.reshape(-1, args["dim"]), bounds))
65    hv, _ = expected_hypervolume(gps, ref_point=args['ref_point'])
66    hvs.append(hv)
67        
68    print(f"Iteration: {i}, New candidate: {newx}, Time: {t2 - t1}, HV: {hv}")
69        
70    train_x = torch.row_stack([train_x, newx.view(-1, args["dim"])])
71    train_y = torch.row_stack([train_y, newy])
72    gps = ModelObject(train_x, train_y, bounds, args["nobj"], args["ncons"], device=device)
73    gps.fit_gp()
74
75    np.save(f"{args["wd"]}/train_x.npy", train_x)
76    np.save(f"{args["wd"]}/train_y.npy", train_y)
77    np.save(f"{args["wd"]}/hv.npy", hvs)
78    np.save(f"{args["wd"]}/times.npy", times)
79
80
81
82

Example Output

Iteration: 0, New candidate: tensor([...]), Time: 0.12s, HV: 4478.89
Iteration: 1, New candidate: tensor([...]), Time: 0.14s, HV: 4480.92
...
Iteration: 49, New candidate: tensor([...]), Time: 0.20s, HV: 4997.88

Usage

To run the script locally, use:

python unconstrained_branin_currin.py

Ensure dependencies such as BoTorch, PyTorch, and qPOTS are installed.