I am searching for the global minimum of a certain function and trying to use its gradient (here same as Jacobin) to guide the step counter. However, my x
is fix and so is my gradient. I am also trying to retrieve the fastest way possible the first x
for which f(x)<1
, therefore I am using a constraint.
- How can I update the
x
input and the Jacobin ? - My
f(x)<1
is not being very effective, so is there any alternative to achieve my requirement?
This is my code (more or less):
class MyBounds(object):
def __init__(self, xmax=[2*np.pi, 2*np.pi, 2*np.pi, 2*np.pi, 1.2, 1.2, 1.2, 1.2], xmin=[0, 0, 0, 0, 0, 0, 0, 0] ):
self.xmax = np.array(xmax)
self.xmin = np.array(xmin)
def __call__(self, **kwargs):
x = kwargs["x_new"]
tmax = bool(np.all(x <= self.xmax))
tmin = bool(np.all(x >= self.xmin))
return tmax and tmin
class MyTakeStep(object):
def __init__(self, stepsize=1):
self.stepsize = stepsize
def compute_step(self, jacobi_matrix, x, i):
if jacobi_matrix[i] < 0: r = np.random.uniform(0, 2*np.pi-x[i])
elif jacobi_matrix[i] > 0: r = np.random.uniform(0-x[i], 0)
else : r = 0
return r
def __call__(self, x):
print("ENTERING fROM CALL")
print("THIS IS X: ", x)
jacobi_matrix = jacobian(x)
print("x : ", x)
print("jacobi: ", jacobi_matrix)
x[0] += self.compute_step(jacobi_matrix, x, 0)
x[1] += self.compute_step(jacobi_matrix, x, 1)
x[2] += self.compute_step(jacobi_matrix, x, 2)
x[3] += self.compute_step(jacobi_matrix, x, 3)
x[4] += self.compute_step(jacobi_matrix, x, 4)
x[5] += self.compute_step(jacobi_matrix, x, 5)
x[6] += self.compute_step(jacobi_matrix, x, 6)
x[7] += self.compute_step(jacobi_matrix, x, 7)
print("newx : ", x)
return x
def f(x):
# objective function componenets
result = g1
result += g2
result += g3
return result
def jacobian(x):
print("input_list in Jacobi: ", x)
# define full derivatives
dG_dphi = dg1_dphi + dg2_dphi + dg3_dphi
dG_dr = dg1_dr + dg2_dr + dg3_dr
gradient = np.hstack((dG_dphi, dG_dr))
print("G: ", gradient.shape, gradient, " \n")
return gradient
def callback(x, f, accept):
print("x: %65s | f: %5s | accept: %5s" % (str([round(e,3) for e in x]), str(round(f, 3)), accept))
def hopping_solver(min_f, min_x, input_excitation):
# define bounds
mybounds = MyBounds()
mytakestep = MyTakeStep()
comb = [deg2rad(phi) for phi in input_excitation[:4]] + input_excitation[4:]
print("comb: ", comb)
min_f = 10
tol = 0
cons = {'type':'ineq','fun': lambda x: 1-f(x)}
k = {"method":'Nelder-Mead', 'constraints': cons, 'jac': jacobian, 'tol': tol}
optimal_c = optimize.basinhopping(f,
x0 = comb,
niter = 1000000,
T = 8,
stepsize = 1,
minimizer_kwargs = k,
take_step = mytakestep,
accept_test = mybounds,
callback = callback,
interval = 100000,
disp = True,
niter_success = None)
print(optimal_c)
min_x, min_f = optimal_c['x'], optimal_c['fun']
comb = min_x
sol = np.array(list([np.rad2deg(phi) for phi in list(optimal_c['x'][:4])]) + list(optimal_c['x'][4:]))
min_x = sol
return min_x, min_f
Any help is much appreciated, thank you in advance.