I'm running fmincon function in python via this interface: https://github.com/byuflowlab/pyfmincon
If I specify upper and lower bounds as
ub = np.array([1.0, 30.0])
lb = np.array([0, 0])
it results in the following error:
Unable to resolve the name 'py.self.neg_log_likelihood'.
Error in my_optimize/fupdate (line 45)
eval(['output = py.', funcname, '(x);']) % output is a cell array with {J, cin}
Error in my_optimize/obj (line 63)
[J, cin, gJ, gcin] = fupdate(x);
Error in fmincon (line 577)
[initVals.f,initVals.g] = feval(funfcn{3},X,varargin{:});
Error in my_optimize (line 28)
[xopt, fopt, exitflag, output] = fmincon(@obj, x0, A, b, Aeq, beq, lb, ub, @con, options);
Caused by:
Failure in initial objective function evaluation. FMINCON cannot continue.
However, if I switch upper and lower bounds the function runs without errors and prints out this message:
Exiting due to infeasibility: at least one lower bound exceeds the corresponding upper bound.
I don't understand how it can run with incorrect bounds. Also, unfortunately people who developed the package are not supporting it anymore, so I can't ask on Github.
my objective function is:
def neg_log_likelihood(self, params):
"""Compute the negative log likelihood of the parameters.
The data consist of a sequence of (cue,action,reward) observations.
"""
df = self.df
if self.model in ('sample_average', 'constant_step_size'):
alpha, beta = params
elif (self.model == 'policy') or (self.model == 'policy_daw'):
if self.param_value['alpha'] == None:
alpha, params = params[0], params[1:]
else:
alpha = self.param_value['alpha']
if self.param_value['beta'] == None:
beta, params = params[0], params[1:]
else:
beta = self.param_value['beta']
if self.param_value['r_bar'] == None:
r_bar, params = params[0], params[1:]
else:
r_bar = self.param_value['r_bar']
df = self.df[self.df['cue'].isin(self.cues)]
actions, rewards = df['action'].values, df['reward'].values
cues = df['cue'].values
prob_log = 0.0
Q = dict([[cue, np.zeros(self.n_actions)] for cue in self.cues])
k = 1
for action, reward, cue in zip(actions, rewards, cues):
if action == 'blue':
action = 1
else:
action = 0
if self.model == 'sample_average':
Q[cue][action] += alpha * (reward - Q[cue][action]) / k
k += 1
elif self.model == 'constant_step_size':
Q[cue][action] = Q[cue][action] + alpha * (reward - Q[cue][action])
#Q[cue] = Q[cue].at[action].set((Q[cue][action] + alpha * (reward - Q[cue][action])))
elif self.model == 'policy':
# We are reusing Q, but the right name should be pi
probs = softmax(Q[cue], beta)
for a in (0,1): # (0, 1) should be something like self.actions
indicator = 1 if a == action else 0
Q[cue][a] += alpha * (reward - r_bar) * (indicator - probs[a])
elif self.model == 'policy_daw': # Daw simplified rule
# We are reusing Q, but the right name should be pi
Q[cue][action] += alpha * (reward - r_bar)
else:
print('Something bad happen :(')
prob_log += np.log(softmax_jnp(Q[cue], beta)[action])
return -prob_log