2

I want to use the hyperparameters optimization using hyperopt, but I have a problem finding the right formulation of the search space for the hyperparameters. the optimal solution of my problem is [0,4050,2100,2100,1200,0,0,450,150].My attempt code:

from gekko import GEKKO
import numpy as np
from hyperopt import fmin, tpe, hp
from hyperopt import STATUS_OK, STATUS_FAIL

# data
P=[13105.11598923, 11261.13968067, 10103.92043191, 8199.51950018,
   6411.29606705,  4753.51971915,  3897.77624628, 2659.30922847,
   1639.99999999]
Q=[0., 4434.40470446, 3808.26080152, 3262.6022579,1256.88696212,0.,
   0.,352.26399841,200.00000001]
V=[22836.72949, 22709.57526, 22158.26541, 21804.24667, 21094.79492,
   20864.73522, 20445.8738 , 19749.82457, 19262.43063]
R=[1.2330e-04, 1.4000e-05, 7.4630e-04, 6.9840e-04, 1.9831e-03,
   9.0530e-04, 2.0552e-03, 4.7953e-03, 5.3434e-03]
Kc=[0.5, 0.35, 0.253, 0.22, 0.276, 0.183, 0.228,0.17,0.207,0.201,
    0.193,0.187,0.211,0.176,0.179, 0.170,0.189,0.187,0.183,0.180,
    0.195,0.174,0.188,0.170,0.183,0.182,0.179]
Qc=[150, 300, 450, 600,750, 900,1050, 1200,1350,1500,1650,1800,
    1950,2100,2250,2400,2550,2700,2850,3000,3150,3300,3450,3600,
    3750,3900,4050]   
Ke=168
T=24*365
N=len(Q) 
Nc=len(Qc)
N,Nc
#Define the search space for the hyperparameters
## the initial value
IV=[[0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0, 0, 0, 0, 0, 0, 0, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0, 0, 1, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0, 1, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]
space = {'x1': hp.choice('x1', IV[0]),
         'x2': hp.choice('x2', IV[1]),
         'x3': hp.choice('x3', IV[2]),
         'x4': hp.choice('x4', IV[3]),
         'x5': hp.choice('x5', IV[4]),
         'x6': hp.choice('x6', IV[5]),
         'x7': hp.choice('x7', IV[6]),
         'x8': hp.choice('x8', IV[7]),
         'x9': hp.choice('x9', IV[8])} 
def objective(params):
    m = GEKKO(remote=False)
    x = m.Array(m.Var,(N,Nc),integer=True,lb=0,ub=1)
    x1,x2,x3,x4,x5,x6,x7,x8,x9 = x
    x1= params['x1']
    x2= params['x2']
    x3= params['x3']
    x4= params['x4']
    x5= params['x5']
    x6= params['x6']
    x7= params['x7']
    x8= params['x8']
    x9= params['x9']
    #constrainte ## one per line
    for i in range(N):
        m.Equation(m.sum([x[i,j]for j in range(Nc)])<=1)
    #constrainte# max of capacitors
    m.Equation(m.sum([m.sum([Qc[j]*x[i,j] 
               for j in range(Nc)])
                for i in range(N)])<=
               m.sum([Q[i]for i in range(N)])) 
    #objective function
    m.Minimize(m.sum([m.sum([((R[i]*T*Ke*(1/V[i]**2)\
               *((P[i]**2)+(Q[i]-Qc[j]*x[i,j])**2))+
               (Kc[j]*Qc[j]*x[i,j]))
               for j in range(Nc)])
               for i in range(N)]))
    m.solver_options = ['minlp_gap_tol 1e-5',\
                        'minlp_maximum_iterations 10000',\
                        'minlp_max_iter_with_int_sol 2000']
    m.options.SOLVER = 1
    m.solve(disp=False,debug=False)
    obj = m.options.objfcnval
    if m.options.APPSTATUS==1:
        s=STATUS_OK
    else:
        s=STATUS_FAIL
    m.cleanup()
    return {'loss':obj, 'status': s, 'x':x}

best = fmin(objective, space, algo=tpe.suggest, max_evals=50)
sol= objective(best)
print(f"Solution Status: {sol['status']}")
print(f"Objective: {sol['loss']:.2f}")
print(f"Solution: {sol['x']}")
print('best:',best)

Qc_added=np.zeros(N)
for i in range(N):
    for j in range(Nc):
        if sol['x'][i][j].value==[1]:
            Qc_added[i]=Qc[j]*sol['x'][i][j].value
        else:
            pass
print(Qc_added)

this code gives me zeros like an optimal solution. I tried also this search space :

space = {'x1': hp.quniform('x1',0,1,Nc),
         'x2': hp.quniform('x2',0,1,Nc),
         'x3': hp.quniform('x3',0,1,Nc),
         'x4': hp.quniform('x4',0,1,Nc),
         'x5': hp.quniform('x5',0,1,Nc),
         'x6': hp.quniform('x6',0,1,Nc),
         'x7': hp.quniform('x7',0,1,Nc),
         'x8': hp.quniform('x8',0,1,Nc),
         'x9': hp.quniform('x9',0,1,Nc)}
John Hedengren
  • 12,068
  • 1
  • 21
  • 25
  • Thanks for posting a follow-up question. For others who come to this question, here is the previous question: https://stackoverflow.com/questions/75237857/how-formulat-my-optimization-problem-with-gekko/75444173 – John Hedengren Feb 24 '23 at 19:41

1 Answers1

0

Hyperopt has a separate hp.choice() or hp.quniform() for every variable. In the case of this optimization problem, there are 9x27=243 variables so it would need x1 through x243, not just x1 through x9 for initial guesses for the local optimizer. The hp.choice() option would only need [0,1] if these are the two starting initial conditions that are needed for the problem. There is a k-Nearest Neighbors hyperparameter search in the Machine Learning for Engineers course and a global optimization example with gekko in the Design Optimization course. I'd recommend these two tutorials to get more familiar with Hyperopt.

Because there is only one non-zero binary variable per row, another way to set up the hyperparameter optimization is to select the index of the non-zero for each row as an initialization. The choices are an integer value between 0 and 26 that are the non-zero entries for the guess.

choices = np.arange(0,27)
space = {'nz1': hp.choice('nz1', choices),
         'nz2': hp.choice('nz2', choices),
         'nz3': hp.choice('nz3', choices),
         'nz4': hp.choice('nz4', choices),
         'nz5': hp.choice('nz5', choices),
         'nz6': hp.choice('nz6', choices),
         'nz7': hp.choice('nz7', choices),
         'nz8': hp.choice('nz8', choices),
         'nz9': hp.choice('nz9', choices)} 

Here is the complete script:

from gekko import GEKKO
import numpy as np
from hyperopt import fmin, tpe, hp
from hyperopt import STATUS_OK, STATUS_FAIL

# data
P=[13105.11598923, 11261.13968067, 10103.92043191, 8199.51950018,
   6411.29606705,  4753.51971915,  3897.77624628, 2659.30922847,
   1639.99999999]
Q=[0., 4434.40470446, 3808.26080152, 3262.6022579,1256.88696212,0.,
   0.,352.26399841,200.00000001]
V=[22836.72949, 22709.57526, 22158.26541, 21804.24667, 21094.79492,
   20864.73522, 20445.8738 , 19749.82457, 19262.43063]
R=[1.2330e-04, 1.4000e-05, 7.4630e-04, 6.9840e-04, 1.9831e-03,
   9.0530e-04, 2.0552e-03, 4.7953e-03, 5.3434e-03]
Kc=[0.5, 0.35, 0.253, 0.22, 0.276, 0.183, 0.228,0.17,0.207,0.201,
    0.193,0.187,0.211,0.176,0.179, 0.170,0.189,0.187,0.183,0.180,
    0.195,0.174,0.188,0.170,0.183,0.182,0.179]
Qc=[150, 300, 450, 600,750, 900,1050, 1200,1350,1500,1650,1800,
    1950,2100,2250,2400,2550,2700,2850,3000,3150,3300,3450,3600,
    3750,3900,4050]   
Ke=168
T=24*365
N=len(Q) 
Nc=len(Qc)
#Define the search space for the hyperparameters
# pick one of the column values to have a non-zero
choices = np.arange(0,27)
space = {'nz1': hp.choice('nz1', choices),
         'nz2': hp.choice('nz2', choices),
         'nz3': hp.choice('nz3', choices),
         'nz4': hp.choice('nz4', choices),
         'nz5': hp.choice('nz5', choices),
         'nz6': hp.choice('nz6', choices),
         'nz7': hp.choice('nz7', choices),
         'nz8': hp.choice('nz8', choices),
         'nz9': hp.choice('nz9', choices)} 
def objective(params):
    m = GEKKO(remote=False)
    x = m.Array(m.Var,(N,Nc),value=0,integer=True,lb=0,ub=1)
    x1,x2,x3,x4,x5,x6,x7,x8,x9 = x
    x1[int(params['nz1'])].value = 1
    x2[int(params['nz2'])].value = 1
    x3[int(params['nz3'])].value = 1
    x4[int(params['nz4'])].value = 1
    x5[int(params['nz5'])].value = 1
    x6[int(params['nz6'])].value = 1
    x7[int(params['nz7'])].value = 1
    x8[int(params['nz8'])].value = 1
    x9[int(params['nz9'])].value = 1
    #constrainte ## one per line
    for i in range(N):
        m.Equation(m.sum([x[i,j] for j in range(Nc)])<=1)
    #constrainte# max of capacitors
    m.Equation(m.sum([m.sum([Qc[j]*x[i,j] 
               for j in range(Nc)])
                for i in range(N)])<=
               m.sum([Q[i]for i in range(N)])) 
    #objective function
    m.Minimize(m.sum([m.sum([((R[i]*T*Ke*(1/V[i]**2)\
               *((P[i]**2)+(Q[i]-Qc[j]*x[i,j])**2))+
               (Kc[j]*Qc[j]*x[i,j]))
               for j in range(Nc)])
               for i in range(N)]))
    m.solver_options = ['minlp_gap_tol 1e-5',\
                        'minlp_maximum_iterations 10000',\
                        'minlp_max_iter_with_int_sol 2000']
    m.options.SOLVER = 1
    m.solve(disp=False,debug=False)
    obj = m.options.objfcnval
    if m.options.APPSTATUS==1:
        s=STATUS_OK
    else:
        s=STATUS_FAIL
    m.cleanup()
    return {'loss':obj, 'status': s, 'x':x}

best = fmin(objective, space, algo=tpe.suggest, max_evals=50)
sol= objective(best)
print(f"Solution Status: {sol['status']}")
print(f"Objective: {sol['loss']:.2f}")
print(f"Solution: {sol['x']}")
print('best:',best)

Qc_added=np.zeros(N)
for i in range(N):
    for j in range(Nc):
        if sol['x'][i][j].value==[1]:
            Qc_added[i]=Qc[j]*sol['x'][i][j].value
        else:
            pass
print(Qc_added)

The best solution appears to be all zeros with an initial guess of:

best: {'nz1': 18, 'nz2': 2, 'nz3': 22, 'nz4': 25, 'nz5': 3,
       'nz6': 16, 'nz7': 10, 'nz8': 9, 'nz9': 16}

It appears that any initial guess leads to the same optimal solution. Here is the same objective function with initial guesses of zeros.

from gekko import GEKKO

# data
P=[13105.11598923, 11261.13968067, 10103.92043191, 8199.51950018,
   6411.29606705,  4753.51971915,  3897.77624628, 2659.30922847,
   1639.99999999]
Q=[0., 4434.40470446, 3808.26080152, 3262.6022579,1256.88696212,0.,
   0.,352.26399841,200.00000001]
V=[22836.72949, 22709.57526, 22158.26541, 21804.24667, 21094.79492,
   20864.73522, 20445.8738 , 19749.82457, 19262.43063]
R=[1.2330e-04, 1.4000e-05, 7.4630e-04, 6.9840e-04, 1.9831e-03,
   9.0530e-04, 2.0552e-03, 4.7953e-03, 5.3434e-03]
Kc=[0.5, 0.35, 0.253, 0.22, 0.276, 0.183, 0.228,0.17,0.207,0.201,
    0.193,0.187,0.211,0.176,0.179, 0.170,0.189,0.187,0.183,0.180,
    0.195,0.174,0.188,0.170,0.183,0.182,0.179]
Qc=[150, 300, 450, 600,750, 900,1050, 1200,1350,1500,1650,1800,
    1950,2100,2250,2400,2550,2700,2850,3000,3150,3300,3450,3600,
    3750,3900,4050]   
Ke=168
T=24*365
N=len(Q) 
Nc=len(Qc)

m = GEKKO(remote=False)
x = m.Array(m.Var,(N,Nc),value=0,integer=True,lb=0,ub=1)
for i in range(N):
    m.Equation(m.sum([x[i,j] for j in range(Nc)])<=1)
m.Equation(m.sum([m.sum([Qc[j]*x[i,j] 
               for j in range(Nc)])
                for i in range(N)])<=
               m.sum([Q[i]for i in range(N)])) 
m.Minimize(m.sum([m.sum([((R[i]*T*Ke*(1/V[i]**2)\
               *((P[i]**2)+(Q[i]-Qc[j]*x[i,j])**2))+
               (Kc[j]*Qc[j]*x[i,j]))
               for j in range(Nc)])
               for i in range(N)]))
m.solver_options = ['minlp_gap_tol 1e-5',\
                    'minlp_maximum_iterations 10000',\
                    'minlp_max_iter_with_int_sol 2000']
m.options.SOLVER = 1
m.solve(disp=True)
print(m.options.objfcnval)
print(x)
 ---------------------------------------------------
 Solver         :  APOPT (v1.0)
 Solution time  :   1.770000001124572E-002 sec
 Objective      :    30829.9697551930     
 Successful solution
 ---------------------------------------------------
John Hedengren
  • 12,068
  • 1
  • 21
  • 25