Пример #1
0
def _minimize_levenberg_marquardt(func, x0, nmr_observations, cl_runtime_info, data=None, options=None):
    options = _clean_options('Levenberg-Marquardt', options)

    nmr_problems = x0.shape[0]
    nmr_parameters = x0.shape[1]

    if nmr_observations < x0.shape[1]:
        raise ValueError('The number of instances per problem must be greater than the number of parameters')

    kernel_data = {'model_parameters': Array(x0, ctype='mot_float_type', mode='rw'),
                   'data': data,
                   'fjac': Zeros((nmr_problems, nmr_parameters, nmr_observations), ctype='mot_float_type',
                                 mode='rw')}

    eval_func = SimpleCLFunction.from_string('''
        void evaluate(local mot_float_type* x, void* data, local mot_float_type* result){
            ''' + func.get_cl_function_name() + '''(x, data, result);
        }
    ''', dependencies=[func])

    optimizer_func = LevenbergMarquardt(eval_func, nmr_parameters, nmr_observations, jacobian_func=None, **options)

    return_code = optimizer_func.evaluate(
        kernel_data, nmr_problems,
        use_local_reduction=all(env.is_gpu for env in cl_runtime_info.get_cl_environments()),
        cl_runtime_info=cl_runtime_info)

    return OptimizeResults({'x': kernel_data['model_parameters'].get_data(),
                            'status': return_code})
Пример #2
0
def _minimize_powell(func, x0, cl_runtime_info, data=None, options=None):
    """
    Options:
        patience (int): Used to set the maximum number of iterations to patience*(number_of_parameters+1)
        reset_method (str): one of 'EXTRAPOLATED_POINT' or 'RESET_TO_IDENTITY' lower case or upper case.
        patience_line_search (int): the patience of the searching algorithm. Defaults to the
            same patience as for the Powell algorithm itself.
    """
    options = _clean_options('Powell', options)

    nmr_problems = x0.shape[0]
    nmr_parameters = x0.shape[1]

    kernel_data = {'model_parameters': Array(x0, ctype='mot_float_type', mode='rw'),
                   'data': data}

    eval_func = SimpleCLFunction.from_string('''
        double evaluate(local mot_float_type* x, void* data){
            return ''' + func.get_cl_function_name() + '''(x, data, 0);
        }
    ''', dependencies=[func])

    optimizer_func = Powell(eval_func, nmr_parameters, **options)

    return_code = optimizer_func.evaluate(
        kernel_data, nmr_problems,
        use_local_reduction=all(env.is_gpu for env in cl_runtime_info.get_cl_environments()),
        cl_runtime_info=cl_runtime_info)

    return OptimizeResults({'x': kernel_data['model_parameters'].get_data(),
                            'status': return_code})
Пример #3
0
def _minimize_levenberg_marquardt(func, x0, nmr_observations, cl_runtime_info, lower_bounds, upper_bounds,
                                  use_local_reduction,
                                  constraints_func=None, data=None, options=None):
    options = options or {}
    nmr_problems = x0.shape[0]
    nmr_parameters = x0.shape[1]

    if nmr_observations < x0.shape[1]:
        raise ValueError('The number of instances per problem must be greater than the number of parameters')

    penalty_data, penalty_func = _get_penalty_function(nmr_parameters, constraints_func)

    eval_func = SimpleCLFunction.from_string('''
        void evaluate(local mot_float_type* x, void* data, local mot_float_type* result){
            double penalty = _mle_penalty(
                x,
                ((_lm_eval_func_data*)data)->data,
                ((_lm_eval_func_data*)data)->lower_bounds,
                ((_lm_eval_func_data*)data)->upper_bounds,
                ''' + str(options.get('penalty_weight', 1e30)) + ''',
                ((_lm_eval_func_data*)data)->penalty_data
            );

            ''' + func.get_cl_function_name() + '''(x, ((_lm_eval_func_data*)data)->data, result);

            if(get_local_id(0) == 0){
                for(int j = 0; j < ''' + str(nmr_observations) + '''; j++){
                    result[j] += penalty;
                }
            }
            barrier(CLK_LOCAL_MEM_FENCE);
        }
    ''', dependencies=[func, penalty_func])

    jacobian_func = _lm_numdiff_jacobian(eval_func, nmr_parameters, nmr_observations)

    optimizer_func = LevenbergMarquardt(eval_func, nmr_parameters, nmr_observations, jacobian_func,
                                        **_clean_options('Levenberg-Marquardt', options))

    kernel_data = {'model_parameters': Array(x0, ctype='mot_float_type', mode='rw'),
                   'data': Struct({'data': data,
                                   'lower_bounds': lower_bounds,
                                   'upper_bounds': upper_bounds,
                                   'penalty_data': penalty_data,
                                   'jacobian_x_tmp': LocalMemory('mot_float_type', nmr_observations)
                                   },
                                  '_lm_eval_func_data')}
    kernel_data.update(optimizer_func.get_kernel_data())

    return_code = optimizer_func.evaluate(
        kernel_data, nmr_problems,
        use_local_reduction=use_local_reduction and all(env.is_gpu for env in cl_runtime_info.cl_environments),
        cl_runtime_info=cl_runtime_info)

    return OptimizeResults({'x': kernel_data['model_parameters'].get_data(),
                            'status': return_code})
Пример #4
0
def _minimize_powell(func, x0, cl_runtime_info, lower_bounds, upper_bounds, use_local_reduction,
                     constraints_func=None, data=None, options=None):
    """
    Options:
        patience (int): Used to set the maximum number of iterations to patience*(number_of_parameters+1)
        reset_method (str): one of 'EXTRAPOLATED_POINT' or 'RESET_TO_IDENTITY' lower case or upper case.
        patience_line_search (int): the patience of the searching algorithm. Defaults to the
            same patience as for the Powell algorithm itself.
    """
    options = options or {}
    nmr_problems = x0.shape[0]
    nmr_parameters = x0.shape[1]

    penalty_data, penalty_func = _get_penalty_function(nmr_parameters, constraints_func)

    eval_func = SimpleCLFunction.from_string('''
        double evaluate(local mot_float_type* x, void* data){
            double penalty = _mle_penalty(
                x,
                ((_powell_eval_func_data*)data)->data,
                ((_powell_eval_func_data*)data)->lower_bounds,
                ((_powell_eval_func_data*)data)->upper_bounds,
                ''' + str(options.get('penalty_weight', 1e30)) + ''',
                ((_powell_eval_func_data*)data)->penalty_data
            );

            double func_val = ''' + func.get_cl_function_name() + '''(x, ((_powell_eval_func_data*)data)->data, 0);

            if(isnan(func_val)){
                return INFINITY;
            }

            return func_val + penalty;
        }
    ''', dependencies=[func, penalty_func])

    optimizer_func = Powell(eval_func, nmr_parameters, **_clean_options('Powell', options))

    kernel_data = {'model_parameters': Array(x0, ctype='mot_float_type', mode='rw'),
                   'data': Struct({'data': data,
                                   'lower_bounds': lower_bounds,
                                   'upper_bounds': upper_bounds,
                                   'penalty_data': penalty_data}, '_powell_eval_func_data')}
    kernel_data.update(optimizer_func.get_kernel_data())

    return_code = optimizer_func.evaluate(
        kernel_data, nmr_problems,
        use_local_reduction=use_local_reduction and all(env.is_gpu for env in cl_runtime_info.cl_environments),
        cl_runtime_info=cl_runtime_info,)

    return OptimizeResults({'x': kernel_data['model_parameters'].get_data(),
                            'status': return_code})
Пример #5
0
def _minimize_subplex(func, x0, cl_runtime_info, lower_bounds, upper_bounds, use_local_reduction,
                      constraints_func=None, data=None, options=None):
    """Variation on the Nelder-Mead Simplex method by Thomas H. Rowan.

    This method uses NMSimplex to search subspace regions for the minimum. See Rowan's thesis titled
    "Functional Stability analysis of numerical algorithms" for more details.

     The scales should satisfy the following constraints:

        .. code-block:: python

            alpha > 0
            0 < beta < 1
            gamma > 1
            gamma > alpha
            0 < delta < 1

    Options:
        patience (int): Used to set the maximum number of iterations to patience*(number_of_parameters+1)
        patience_nmsimplex (int): The maximum patience for each subspace search.
            For each subspace search we set the number of iterations to patience*(number_of_parameters_subspace+1)
        scale (double): the scale of the initial simplex, default 1.0
        alpha (double): reflection coefficient, default 1.0
        beta (double): contraction coefficient, default 0.5
        gamma (double); expansion coefficient, default 2.0
        delta (double); shrinkage coefficient, default 0.5
        psi (double): subplex specific, simplex reduction coefficient, default 0.001.
        omega (double): subplex specific, scaling reduction coefficient, default 0.01
        min_subspace_length (int): the minimum subspace length, defaults to min(2, n).
            This should hold: (1 <= min_s_d <= max_s_d <= n and min_s_d*ceil(n/nsmax_s_dmax) <= n)
        max_subspace_length (int): the maximum subspace length, defaults to min(5, n).
            This should hold: (1 <= min_s_d <= max_s_d <= n and min_s_d*ceil(n/max_s_d) <= n)

        adaptive_scales (boolean): if set to True we use adaptive scales instead of the default scale values.
            This sets the scales to:

            .. code-block:: python

                n = <# parameters>

                alpha = 1
                beta  = 0.75 - 1.0 / (2 * n)
                gamma = 1 + 2.0 / n
                delta = 1 - 1.0 / n

    References:
        [1] Gao F, Han L. Implementing the Nelder-Mead simplex algorithm with adaptive parameters.
              Comput Optim Appl. 2012;51(1):259-277. doi:10.1007/s10589-010-9329-3.
    """
    options = options or {}
    nmr_problems = x0.shape[0]
    nmr_parameters = x0.shape[1]

    penalty_data, penalty_func = _get_penalty_function(nmr_parameters, constraints_func)

    eval_func = SimpleCLFunction.from_string('''
        double evaluate(local mot_float_type* x, void* data){
            double penalty = _mle_penalty(
                x,
                ((_subplex_eval_func_data*)data)->data,
                ((_subplex_eval_func_data*)data)->lower_bounds,
                ((_subplex_eval_func_data*)data)->upper_bounds,
                ''' + str(options.get('penalty_weight', 1e30)) + ''',
                ((_subplex_eval_func_data*)data)->penalty_data
            );

            double func_val = ''' + func.get_cl_function_name() + '''(x, ((_subplex_eval_func_data*)data)->data, 0);

            if(isnan(func_val)){
                return INFINITY;
            }

            return func_val + penalty;
        }
    ''', dependencies=[func, penalty_func])

    optimizer_func = Subplex(eval_func, nmr_parameters, **_clean_options('Subplex', options))

    kernel_data = {'model_parameters': Array(x0, ctype='mot_float_type', mode='rw'),
                   'data': Struct({'data': data,
                                   'lower_bounds': lower_bounds,
                                   'upper_bounds': upper_bounds,
                                   'penalty_data': penalty_data}, '_subplex_eval_func_data')}
    kernel_data.update(optimizer_func.get_kernel_data())

    return_code = optimizer_func.evaluate(
        kernel_data, nmr_problems,
        use_local_reduction=use_local_reduction and all(env.is_gpu for env in cl_runtime_info.cl_environments),
        cl_runtime_info=cl_runtime_info)

    return OptimizeResults({'x': kernel_data['model_parameters'].get_data(),
                            'status': return_code})
Пример #6
0
def _minimize_nmsimplex(func, x0, cl_runtime_info, lower_bounds, upper_bounds, use_local_reduction,
                        constraints_func=None, data=None, options=None):
    """Use the Nelder-Mead simplex method to calculate the optimimum.

    The scales should satisfy the following constraints:

        .. code-block:: python

            alpha > 0
            0 < beta < 1
            gamma > 1
            gamma > alpha
            0 < delta < 1

    Options:
        patience (int): Used to set the maximum number of iterations to patience*(number_of_parameters+1)
        scale (double): the scale of the initial simplex, default 1.0
        alpha (double): reflection coefficient, default 1.0
        beta (double): contraction coefficient, default 0.5
        gamma (double); expansion coefficient, default 2.0
        delta (double); shrinkage coefficient, default 0.5
        adaptive_scales (boolean): if set to True we use adaptive scales instead of the default scale values.
            This sets the scales to:

            .. code-block:: python

                n = <# parameters>

                alpha = 1
                beta  = 0.75 - 1.0 / (2 * n)
                gamma = 1 + 2.0 / n
                delta = 1 - 1.0 / n

            Following the paper [1]

    References:
        [1] Gao F, Han L. Implementing the Nelder-Mead simplex algorithm with adaptive parameters.
              Comput Optim Appl. 2012;51(1):259-277. doi:10.1007/s10589-010-9329-3.
    """
    options = options or {}
    nmr_problems = x0.shape[0]
    nmr_parameters = x0.shape[1]

    penalty_data, penalty_func = _get_penalty_function(nmr_parameters, constraints_func)

    eval_func = SimpleCLFunction.from_string('''
        double evaluate(local mot_float_type* x, void* data){
            double penalty = _mle_penalty(
                x,
                ((_nmsimplex_eval_func_data*)data)->data,
                ((_nmsimplex_eval_func_data*)data)->lower_bounds,
                ((_nmsimplex_eval_func_data*)data)->upper_bounds,
                ''' + str(options.get('penalty_weight', 1e30)) + ''',
                ((_nmsimplex_eval_func_data*)data)->penalty_data
            );

            double func_val = ''' + func.get_cl_function_name() + '''(x, ((_nmsimplex_eval_func_data*)data)->data, 0);

            if(isnan(func_val)){
                return INFINITY;
            }

            return func_val + penalty;
        }
    ''', dependencies=[func, penalty_func])

    optimizer_func = NMSimplex('evaluate', nmr_parameters, dependencies=[eval_func],
                               **_clean_options('Nelder-Mead', options))

    kernel_data = {'model_parameters': Array(x0, ctype='mot_float_type', mode='rw'),
                   'data': Struct({'data': data,
                                   'lower_bounds': lower_bounds,
                                   'upper_bounds': upper_bounds,
                                   'penalty_data': penalty_data}, '_nmsimplex_eval_func_data')}
    kernel_data.update(optimizer_func.get_kernel_data())

    return_code = optimizer_func.evaluate(
        kernel_data, nmr_problems,
        use_local_reduction=use_local_reduction and all(env.is_gpu for env in cl_runtime_info.cl_environments),
        cl_runtime_info=cl_runtime_info)

    return OptimizeResults({'x': kernel_data['model_parameters'].get_data(),
                            'status': return_code})
Пример #7
0
def _minimize_nmsimplex(func, x0, cl_runtime_info, data=None, options=None):
    """Use the Nelder-Mead simplex method to calculate the optimimum.

    The scales should satisfy the following constraints:

        .. code-block:: python

            alpha > 0
            0 < beta < 1
            gamma > 1
            gamma > alpha
            0 < delta < 1

    Options:
        patience (int): Used to set the maximum number of iterations to patience*(number_of_parameters+1)
        scale (double): the scale of the initial simplex, default 1.0
        alpha (double): reflection coefficient, default 1.0
        beta (double): contraction coefficient, default 0.5
        gamma (double); expansion coefficient, default 2.0
        delta (double); shrinkage coefficient, default 0.5
        adaptive_scales (boolean): if set to True we use adaptive scales instead of the default scale values.
            This sets the scales to:

            .. code-block:: python

                n = <# parameters>

                alpha = 1
                beta  = 0.75 - 1.0 / (2 * n)
                gamma = 1 + 2.0 / n
                delta = 1 - 1.0 / n

            Following the paper [1]

    References:
        [1] Gao F, Han L. Implementing the Nelder-Mead simplex algorithm with adaptive parameters.
              Comput Optim Appl. 2012;51(1):259-277. doi:10.1007/s10589-010-9329-3.
    """
    options = _clean_options('Nelder-Mead', options)

    nmr_problems = x0.shape[0]
    nmr_parameters = x0.shape[1]

    kernel_data = {'model_parameters': Array(x0, ctype='mot_float_type', mode='rw'),
                   'data': data}

    eval_func = SimpleCLFunction.from_string('''
        double evaluate(local mot_float_type* x, void* data){
            return ''' + func.get_cl_function_name() + '''(x, data, 0);
        }
    ''', dependencies=[func])

    optimizer_func = NMSimplex('evaluate', nmr_parameters, dependencies=[eval_func], **options)

    return_code = optimizer_func.evaluate(
        kernel_data, nmr_problems,
        use_local_reduction=all(env.is_gpu for env in cl_runtime_info.get_cl_environments()),
        cl_runtime_info=cl_runtime_info)

    return OptimizeResults({'x': kernel_data['model_parameters'].get_data(),
                            'status': return_code})