botorch icon indicating copy to clipboard operation
botorch copied to clipboard

[Bug] Penicillin test function gives better values than in the reference paper

Open mfeurer opened this issue 2 years ago • 1 comments

🐛 Bug

The penicillin test function gives better values than in the reference paper. In the original paper, the authors sample 10**6 configurations and obtain an optimum around -14.65. Doing the same with the BoTorch implementation leads to values smaller than -20.

To reproduce

** Code snippet to reproduce **

import numpy as np
import torch

from botorch.test_functions.multi_objective import Penicillin
from botorch.utils.transforms import unnormalize

p = Penicillin(noise_std=0, negate=True)

# Draw a lot of samples as in the original paper
input_orig = torch.tensor(np.random.random((1000000, 7))).double()
input = unnormalize(input_orig, bounds=torch.tensor(p._bounds).transpose(0, 1))
values = p.evaluate_true(input)[:, 0]
argmin = np.argmin(values.numpy())
print(values[argmin], input[argmin], input_orig[argmin])

# Check whether this value might be due to scalarization
print(p.evaluate_true(input[argmin]))

** Stack trace/error message **

tensor(-23.1735, dtype=torch.float64) tensor([8.6234e+01, 1.1553e+00, 3.0218e+02, 1.7137e+01, 3.2586e-02, 6.2063e+02,
        5.3257e+00], dtype=torch.float64) tensor([0.4372, 0.0616, 0.9176, 0.9519, 0.0461, 0.6032, 0.2171],
       dtype=torch.float64)
tensor([-23.1735,  29.2081, 496.0000], dtype=torch.float64)

Expected Behavior

A value around -14.65

System information

Please complete the following information:

  • 0.7.0
  • 1.9.0
  • 1.13.1+cu117
  • Ubuntu 20.04

Additional context

I tried to feed the found value into the original code from https://github.com/HarryQL/TuRBO-Penicillin but that fails with the best value found with the BoTorch Penicillin function:

import numpy as np
import torch

# X: biomass concentration
# g/L
# X_0 = 0.1

# S:substrate concentration
# g/L
# S_0 = 0.1

# CL:dissolved oxygen concentration

# P: penicillin concentration
# g/L
# P_0 = 0


# CO2:carbon dioxide concentration;

# H:hydrogen ion concentration for pH

# T: temperature.

C_L_star = 8.26

Y_xs = 0.45
Y_xo = 0.04
Y_ps = 0.90
Y_po = 0.20

K_1 = 10**(-10)
K_2 = 7 * 10**(-5)
m_X = 0.014
m_o = 0.467

alpha_1 = 0.143
alpha_2 = 4*10**(-7)
alpha_3 = 10**(-4)
mu_X = 0.092
K_X = 0.15
# K_ox = 2*10**(-2)
# K_op = 5*10**(-4)
mu_p = 0.005
K_p = 0.0002
K_I = 0.10
p = 3
K = 0.04
k_g = 7 * 10**(3)
E_g = 5100
k_d = 10**(33)
E_d = 50000

# rou_dot_C_p = 1/1500
# rou_c_dot_C_pc = 1/2000

rou_dot_C_p = 1000
rou_c_dot_C_pc = 1000

r_q1 = 60
r_q2 = 1.6783 * 10**(-4)
a = 1000
b = 0.60

alpha = 70
beta = 0.4
lambd = 2.5 * 10**(-4)
gamma = 10**(-5)

# kelvin
T_v = 273
T_o = 373

# CAL/(MOL K)
R = 1.9872

# total unit time: hrs
t = 2500
V_max = 180
V_limits = [60, 120]
X_limits = [0.05, 18]
CO2 = 0
T_limits = [293, 303]
S_limits = [0.05, 18]
F_limits = [0.01, 0.50]
s_f_limits = [500, 700]
H_limits = [5, 6.5]
limits = [V_limits, X_limits, T_limits, S_limits, F_limits, s_f_limits, H_limits]


def penicilin_exp_BO(X_input):
    #     V_limits, X_limits, T_limits, S_limits, F_limits, s_f_limits, H_limits

    V, X, T, S, F, s_f, H_ = X_input[:, 0], X_input[:, 1], X_input[:, 2], X_input[:, 3], X_input[:, 4], X_input[:, 5], X_input[:, 6]

    P = 0
    CO2 = 0
    t = 2500

    l_P = []
    l_V = []
    l_X = []
    l_T = []
    l_S = []
    l_F = []
    l_s_f = []
    l_H_ = []
    l_CO2 = []
    l_t = []

    l_P.append(P)
    l_V.append(V)
    l_X.append(X)
    l_T.append(T)
    l_S.append(S)
    l_F.append(F)
    l_s_f.append(s_f)
    l_H_.append(H_)
    l_CO2.append(CO2)
    l_t.append(0)

    H = 10 ** (-H_)

    for i in np.arange(t) + 1:

        F_loss = V * lambd * (np.exp(5 * ((T - T_o) / (T_v - T_o))) - 1)
        dV_dt = F - F_loss

        mu = (mu_X / (1 + K_1 / H + H / K_2)) * (S / (K_X * X + S)) * (
                    (k_g * np.exp(-E_g / (R * T))) - (k_d * np.exp(-E_d / (R * T))))
        dX_dt = mu * X - (X / V) * dV_dt

        mu_pp = mu_p * (S / (K_p + S + S ** 2 / K_I))
        dS_dt = - (mu / Y_xs) * X - (mu_pp / Y_ps) * X - m_X * X + F * s_f / V - (S / V) * dV_dt

        dP_dt = (mu_pp * X) - K * P - (P / V) * dV_dt

        dCO2_dt = alpha_1 * dX_dt + alpha_2 * X + alpha_3

        # UPDATE
        P = P + dP_dt
        V = V + dV_dt
        X = X + dX_dt
        S = S + dS_dt
        CO2 = CO2 + dCO2_dt

        l_P.append(P)
        l_V.append(V)
        l_X.append(X)
        l_T.append(T)
        l_S.append(S)
        l_F.append(F)
        l_s_f.append(s_f)
        l_H_.append(H_)
        l_CO2.append(CO2)
        l_t.append(i)

        if V > V_max:
            #             print('Too large V')
            break

        if S < 0:
            #             print('Too small S')
            break

        if dP_dt < 10e-12:
            #             print('Converged P')
            break

    print(P)
    return -P


query = [8.6234e+01, 1.1553e+00, 3.0218e+02, 1.7137e+01, 3.2586e-02, 6.2063e+02, 5.3257e+00]
print(query)
print(
    penicilin_exp_BO(
        torch.tensor(query).reshape((1, -1)).float()
    )
)

which gives

[86.234, 1.1553, 302.18, 17.137, 0.032586, 620.63, 5.3257]
Traceback (most recent call last):
  File "/home/feurerm/projects/2022_pfns_4_bo/local_harryql.py", line 177, in <module>
    penicilin_exp_BO(
  File "/home/feurerm/projects/2022_pfns_4_bo/local_harryql.py", line 130, in penicilin_exp_BO
    (k_g * np.exp(-E_g / (R * T))) - (k_d * np.exp(-E_d / (R * T))))
RuntimeError: Overflow when unpacking long

mfeurer avatar Jan 18 '23 15:01 mfeurer

@sdaulton any idea what could be going on here? Given the error and looking through the code it may well be that there are some numerical issues going on (in either implementation).

Balandat avatar Jan 18 '23 16:01 Balandat