FMINCON runs with lower and upper bound variables switched, but doesn't run when bounds are specified correctly

192 Views Asked by At

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
0

There are 0 best solutions below