':param loss: Symbolic expression for the loss function.
:param target: A parameterized object to optimize over. It should implement methods of the
:class:`rllab.core.paramerized.Parameterized` class.
:param leq_constraint: A constraint provided as a tuple (f, epsilon), of the form f(*inputs) <= epsilon.
:param inputs: A list of symbolic variables as inputs, which could be subsampled if needed. It is assumed
that the first dimension of these inputs should correspond to the number of data points
:param extra_inputs: A list of symbolic variables as extra inputs which should not be subsampled
:return: No return value.'

def update_opt(self, loss, target, leq_constraint, inputs, extra_inputs=None, constraint_name='constraint', *args, **kwargs):

    inputs = tuple(inputs)
    if (extra_inputs is None):
        extra_inputs = tuple()
    else:
        extra_inputs = tuple(extra_inputs)
    (constraint_term, constraint_value) = leq_constraint
    params = target.get_params(trainable=True)
    grads = theano.grad(loss, wrt=params, disconnected_inputs='warn')
    flat_grad = ext.flatten_tensor_variables(grads)
    self._hvp_approach.update_opt(f=constraint_term, target=target, inputs=(inputs + extra_inputs), reg_coeff=self._reg_coeff)
    self._target = target
    self._max_constraint_val = constraint_value
    self._constraint_name = constraint_name
    self._opt_fun = ext.lazydict(f_loss=(lambda : ext.compile_function(inputs=(inputs + extra_inputs), outputs=loss, log_name='f_loss')), f_grad=(lambda : ext.compile_function(inputs=(inputs + extra_inputs), outputs=flat_grad, log_name='f_grad')), f_constraint=(lambda : ext.compile_function(inputs=(inputs + extra_inputs), outputs=constraint_term, log_name='constraint')), f_loss_constraint=(lambda : ext.compile_function(inputs=(inputs + extra_inputs), outputs=[loss, constraint_term], log_name='f_loss_constraint')))
