Exemplo n.º 1
0
def minimizeIteratively(function, *parameters):
    """Choose parameters to minimize 'function'.

    This function is similar to 'minimize', except that it proceeds by
    minimizing the parameters one at a time instead of
    simultaneously."""

    if isinstance(function, str):
        function = hep.expr.parse(function)
    if not callable(function):
        raise TypeError, \
              "'function' must be callable or an expression string"
    parameters = normalizeParameters(parameters)
    num_parameters = len(parameters)
    
    for count in range(4):
        indices = range(num_parameters)
        optimal_values = num_parameters * [ None ]
        for index in indices:
            parameter_name = parameters[index][0]

            min_parms = [
                (name, val, None, (0, 0))
                for (name, val, s, (l, h)) in parameters[: index] ] \
                + [ parameters[index], ] \
                + [
                (name, val, None, (0, 0))
                for (name, val, s, (l, h)) in parameters[index + 1: ] ]
            result = ext.minuit_minimize(function, min_parms, verbose)
        
            # print '  %s = %f' \
            #       % (parameter_name, result.values[parameter_name])
            optimal_values[index] = result.values[parameter_name]
            sys.stdout.flush()
            
        for index in range(num_parameters):
            name, value, step, (lo, hi) = parameters[index]
            value = optimal_values[index]
            parameters[index] = (name, value, step, (lo, hi))

        # print 'figure of merit = %f' % result.minimum
        # print

    return parameters
Exemplo n.º 2
0
def minimize(function, parameters, verbose=False, minos=False,
             negate=False):
    """Choose parameters to minimize 'function'.

    Using Minuit, find values of named parameters that minimize the
    value of 'function', which may be any callable (including an
    'Expression' object).

    Note that fixed parameters are *not* registered in Minuit as (fixed)
    parameters; Minuit in fact does not know anything about them.  They
    are still passed to 'function' though.  This permits arbitrarily
    many non-floating parameters to be used without exceeding Minuit's
    limit of 100 parameters.

    'function' -- A callable object.  It will be called with keyword
    arguments (only), whose names are specified in 'parameters'.  All
    required arguments must be satisfied from 'parameters'.

    'parameters' -- One or more parameters to choose.  Each may be
    either a string name of the parameter, or a tuple '(name,
    initial_value, step_size, low, high)'.  The second and subsequent
    elements in the tuple may be omitted.

      'initial_value' -- The starting value for the parameter.  If
      omitted, the default is zero (which may not be appropriate, for
      some functions).

      'step_size' -- The starting step size.  If omitted or 'None', the
      parameter is fixed as a constant.

      'low', 'high' -- Constraints on the parameter value; if they are
      omitted (or both zero), the parameter is unconstrained.

    'verbose' -- If true, print verbose output.

    'minos' -- If true, use the MINOS algorithm to compute a better
    covariance matrix.

    'negate' -- If true, minimizes the value of '-function'.

    returns -- A 'Result' instance."""

    if isinstance(function, str):
        function = hep.expr.parse(function)
    if not callable(function):
        raise TypeError, \
              "'function' must be callable or an expression string"
    parameters = normalizeParameters(parameters)
        
    # Do the fit.
    start_time = time.time()
    result = ext.minuit_minimize(
        function, parameters, verbose, minos, negate)
    end_time = time.time()

    # Store the parameter settings.
    result.parameters = dict([ (p[0], p[1 :]) for p in parameters ])
    # Store the elapsed time.
    result.elapsed_time = end_time - start_time
    # All done.
    return result
Exemplo n.º 3
0
def maximumLikelihoodFit(likelihood, parameters, samples,
                         normalization_range=None, extended_fn=None,
                         verbose=False, minos=False):
    """Perform an unbinned maximum likelihood fit.

    Fit the 'parameters' of a 'likelihood' function to maximize the
    likelihood of 'samples'.

    If 'extended_fn' is provided, performs an extended maximum
    likelihood fit, where 'extended_fn' is the scale function for
    'likelihood'.  If 'extended_fn' is not provided, performs an
    ordinary maximum likelihood fit.

    'likelihood' -- The likelihood function or expression.

    'parameters' -- A sequence of parameters.  Each is of the form
    '(name, initial_value, step_size, lower_bound, upper_bound)', where
    everything after the 'name' may be omitted.

    'samples' -- An iterable of samples.  Each item is a mapping of
    sample variable name to value.  An iterator must not be used here;
    the function needs to iterate over the samples multiple times.

    'normalization_range' -- The likelihood function in a maximum
    likelihood fit must be normalized over the sample space.  If
    'likelihood' is already normalized, this parameter may be 'None'.
    Otherwise, it is a sequence of integration ranges of the form
    '(var_name, lo, hi)', over which the likelihood function is
    numerically integrated for each choice of parameters.  The 'lo' and
    'hi' values may be constants or expressions involving the
    parameters.

    'extended_fn' -- If provided, the function to use in an extended
    maximum likelihood fit.

    returns -- A minimization 'Result' object."""

    # Convert the likelihood function to an expression object.
    likelihood = hep.expr.asExpression(likelihood)
    # Set the types of the symbols for the sample variables and
    # parameters to 'float'.  This will produce better compiled
    # expressions.
    likelihood = hep.expr.op.setTypesFixed(likelihood, None, float)

    # Clean up the parameters specification.
    parameters = normalizeParameters(parameters)

    if normalization_range is not None:
        # Convert the normalization range bounds to expression objects. 
        normalization_range = [
            (var, hep.expr.asExpression(lo), hep.expr.asExpression(hi))
             for (var, lo, hi) in normalization_range ]

    if extended_fn is not None:
        # Convert the extended function to an expression object.
        extended_fn = hep.expr.asExpression(extended_fn)
        # As with the likelihood function, all symbol types are floats.
        extended_fn = hep.expr.op.setTypesFixed(extended_fn, None, float)
        # Use its evaluate function.
        extended_fn = extended_fn.evaluate

    # Get busy.
    result = ext.minuit_maximumLikelihoodFit(
        likelihood, parameters, samples, normalization_range,
        extended_fn, verbose, minos)
    result.parameters = dict([ (p[0], p[1 :]) for p in parameters ])

    # Construct the resulting likelihood function.
    fit_likelihood = hep.expr.substitute(likelihood, **result.values)
    # Normalize it, if necessary.
    if normalization_range is not None:
        from hep.cernlib import integrate
        integral = integrate(fit_likelihood, *[
            (name, lo(**result.values), hi(**result.values))
            for (name, lo, hi) in normalization_range ])
        fit_likelihood = hep.expr.Multiply(
            fit_likelihood, hep.expr.Constant(1 / integral))
    result.likelihood = fit_likelihood
        
    return result