コード例 #1
0
def _tau_to_kappa(tau):
    """Using non-linear optimization, convert the NODDI-DTI Tau variables to NODDI kappa's.

    Args:
        tau (ndarray): the list of tau's per voxel.

    Returns:
        ndarray: the list of corresponding kappa's
    """
    tau_func = SimpleCLFunction.from_string('''
        double tau(double kappa){
            if(kappa < 1e-12){
                return 1/3.0;
            }
            return 0.5 * ( 1 / ( sqrt(kappa) * dawson(sqrt(kappa) ) ) - 1/kappa);
        }''',
                                            dependencies=[dawson()])

    objective_func = SimpleCLFunction.from_string('''
        double tau_to_kappa(local const mot_float_type* const x, void* data, local mot_float_type* objective_list){
            return pown(tau(x[0]) - ((_tau_to_kappa_data*)data)->tau, 2); 
        }
    ''',
                                                  dependencies=[tau_func])

    kappa = minimize(objective_func,
                     np.ones_like(tau),
                     data=Struct(
                         {'tau': Array(tau, 'mot_float_type', as_scalar=True)},
                         '_tau_to_kappa_data')).x
    kappa[kappa > 64] = 1
    kappa[kappa < 0] = 1
    return kappa
コード例 #2
0
def _tau_to_kappa(tau):
    """Using non-linear optimization, convert the NODDI-DTI Tau variables to NODDI kappa's.

    Args:
        tau (ndarray): the list of tau's per voxel.

    Returns:
        ndarray: the list of corresponding kappa's
    """
    tau_func = SimpleCLFunction.from_string('''
        mot_float_type tau(mot_float_type kappa){
            if(kappa < 1e-12){
                return 1/3.0;
            }
            return 0.5 * ( 1 / ( sqrt(kappa) * dawson(sqrt(kappa) ) ) - 1/kappa);
        }''',
                                            dependencies=[dawson()])

    objective_func = SimpleCLFunction.from_string('''
        double tau_to_kappa(local const mot_float_type* const x, void* data, local mot_float_type* objective_list){
            return pown(tau(x[0]) - *((mot_float_type*)data), 2); 
        }
    ''',
                                                  dependencies=[tau_func])

    kappa = minimize(objective_func,
                     np.ones_like(tau),
                     data=Array(tau, 'mot_float_type')).x
    return np.clip(kappa, 0, 64)
コード例 #3
0
    def evaluate(self, *args, **kwargs):
        if not any(
                isinstance(p, DataCacheParameter)
                for p in self._parameter_list):
            return super().evaluate(*args, **kwargs)

        cache_struct = self.get_cache_struct('private')[self.name]
        cache_param_name = self._get_cache_parameter().name

        if isinstance(args[0], (tuple, list)):
            args = list(args)
            args[0] = tuple(args[0]) + (cache_struct, )
        else:
            args[0][cache_param_name] = cache_struct

        cache_init_func = self.get_cache_init_function()

        with_cache_func = SimpleCLFunction(
            self._return_type,
            '_{}'.format(self._function_name),
            self._parameter_list,
            '''
                {cache_init_func_name}({cache_params});
                return {parent_func_name}({parent_func_params});
            '''.format(
                cache_init_func_name=cache_init_func.get_cl_function_name(),
                parent_func_name=self.get_cl_function_name(),
                cache_params=', '.join(
                    [p.name for p in cache_init_func.get_parameters()]),
                parent_func_params=', '.join(
                    [p.name for p in self.get_parameters()])),
            dependencies=[cache_init_func, self])

        return with_cache_func.evaluate(*args, **kwargs)
コード例 #4
0
def parse_cl_function(cl_code, dependencies=()):
    """Parse the given OpenCL string to a single SimpleCLFunction.

    If the string contains more than one function, we will return only the last, with all the other added as a
    dependency.

    Args:
        cl_code (str): the input string containing one or more functions.
        dependencies (Iterable[CLCodeObject]): The list of CL libraries this function depends on

    Returns:
        mot.lib.cl_function.SimpleCLFunction: the CL function for the last function in the given strings.
    """
    from mot.lib.cl_function import SimpleCLFunction

    def separate_cl_functions(input_str):
        """Separate all the OpenCL functions.

        This creates a list of strings, with for each function found the OpenCL code.

        Args:
            input_str (str): the string containing one or more functions.

        Returns:
            list: a list of strings, with one string per found CL function.
        """
        class Semantics:

            def __init__(self):
                self._functions = []

            def result(self, ast):
                return self._functions

            def arglist(self, ast):
                if ast == '()':
                    return '()'
                return '({})'.format(', '.join(ast))

            def function(self, ast):
                def join(items):
                    result = ''
                    for item in items:
                        if isinstance(item, str):
                            result += item
                        else:
                            result += join(item)
                    return result

                self._functions.append(join(ast).strip())
                return ast

        return _extract_cl_functions_parser.parse(input_str, semantics=Semantics())

    functions = separate_cl_functions(cl_code)
    return SimpleCLFunction.from_string(functions[-1], dependencies=list(dependencies or []) + [
        SimpleCLFunction.from_string(s) for s in functions[:-1]])
コード例 #5
0
def parse_cl_function(cl_code, dependencies=(), cl_extra=None):
    """Parse the given OpenCL string to a single SimpleCLFunction.

    If the string contains more than one function, we will return only the last, with all the other added as a
    dependency.

    Args:
        cl_code (str): the input string containing one or more functions.
        dependencies (list or tuple of CLLibrary): The list of CL libraries this function depends on
        cl_extra (str): extra CL code for this function that does not warrant an own function.
            This is prepended to the function body.

    Returns:
        mot.lib.cl_function.SimpleCLFunction: the CL function for the last function in the given strings.
    """
    from mot.lib.cl_function import SimpleCLFunction

    def separate_cl_functions(input_str):
        """Separate all the OpenCL functions.

        This creates a list of strings, with for each function found the OpenCL code.

        Args:
            input_str (str): the string containing one or more functions.

        Returns:
            list: a list of strings, with one string per found CL function.
        """
        class Semantics:
            def __init__(self):
                self._functions = []

            def result(self, ast):
                return self._functions

            def function(self, ast):
                def join(items):
                    result = ''
                    for item in items:
                        if isinstance(item, str):
                            result += item
                        else:
                            result += join(item)
                    return result

                self._functions.append(join(ast).strip())
                return ast

        return _cl_functions_parser.parse(input_str, semantics=Semantics())

    functions = separate_cl_functions(cl_code)
    return SimpleCLFunction.from_string(
        functions[-1],
        dependencies=list(dependencies or []) +
        [SimpleCLFunction.from_string(s) for s in functions[:-1]],
        cl_extra=cl_extra)
コード例 #6
0
ファイル: compartment_models.py プロジェクト: sudesnac/MDT
    def _get_proposal_callbacks(self, template, parameter_list):
        """Get a list of proposal callback functions.

        These functions are (indirectly) called by a MCMC sample routine to finalize the new proposal vector.

        Returns:
            List[(Tuple, mot.lib.cl_function.CLFunction)]: a list of proposal callback functions coupled with
                references to the compartment parameters used in the function.
        """
        callbacks = []

        def existing_parameters(param_list):
            param_names = [p.name for p in parameter_list]
            return all(p in param_names for p in param_list)

        def get_corresponding_param(param_name):
            for p in parameter_list:
                if p.name == param_name:
                    return p

        if template.spherical_parameters is not None and existing_parameters(
                template.spherical_parameters):
            corresponding_params = [
                get_corresponding_param(p)
                for p in template.spherical_parameters
            ]

            func = SimpleCLFunction(
                'void', 'proposal_callback_spherical_{}'.format(template.name),
                ['mot_float_type* theta', 'mot_float_type* phi'], '''
                    if(*phi > M_PI_F){
                        *phi -= M_PI_F;
                        *theta = M_PI_F - *theta;
                    }
                    else if(*phi < 0){
                        *phi += M_PI_F;
                        *theta = M_PI_F - *theta;
                    }
            ''')
            callbacks.append((corresponding_params, func))

        for p in parameter_list:
            if hasattr(p, 'sampling_proposal_modulus'
                       ) and p.sampling_proposal_modulus is not None:
                func = SimpleCLFunction(
                    'void',
                    'proposal_callback_{}_{}'.format(template.name, p.name),
                    ['mot_float_type* ' + p.name],
                    '*{0} = *{0} - floor(*{0} / {1}) * {1};'.format(
                        p.name, p.sampling_proposal_modulus))

                callbacks.append(([p], func))

        return callbacks
コード例 #7
0
    def get_cache_init_function(self):
        if not self.get_cache_struct('private'):
            return None

        dependency_calls = []
        cache_init_funcs = []
        for dependency in self.get_dependencies():
            if isinstance(dependency, CompartmentModel):
                cache_init_func = dependency.get_cache_init_function()
                if cache_init_func:
                    params = []
                    for p in cache_init_func.get_parameters():
                        if isinstance(p, DataCacheParameter):
                            params.append('{}->{}'.format(
                                p.name, dependency.get_cl_function_name()))
                        else:
                            params.append(p.name)
                    dependency_calls.append('{}({});'.format(
                        cache_init_func.get_cl_function_name(),
                        ', '.join(params)))
                    cache_init_funcs.append(cache_init_func)

        return SimpleCLFunction(
            'void',
            '{}_init_cache'.format(self._function_name), [
                p for p in self.get_parameters()
                if isinstance(p, (FreeParameter, DataCacheParameter,
                                  NoiseStdInputParameter))
            ],
            self._cache_info.cl_code + '\n'.join(dependency_calls),
            dependencies=cache_init_funcs + self.get_dependencies())
コード例 #8
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})
コード例 #9
0
    def _get_signal_estimates(self, roi_indices):
        self._model.set_input_data(self._input_data, suppress_warnings=True)

        parameters = self._x_opt_array[roi_indices]
        kernel_data = {
            'data':
            self._model.get_kernel_data().get_subset(roi_indices),
            'parameters':
            Array(parameters, ctype='mot_float_type'),
            'estimates':
            Zeros((parameters.shape[0], self._model.get_nmr_observations()),
                  'mot_float_type')
        }

        eval_function_info = self._model.get_model_eval_function()
        simulate_function = SimpleCLFunction.from_string(
            '''
                void simulate(void* data, local mot_float_type* parameters, global mot_float_type* estimates){
                    for(uint i = 0; i < ''' +
            str(self._model.get_nmr_observations()) + '''; i++){
                        estimates[i] = ''' +
            eval_function_info.get_cl_function_name() +
            '''(data, parameters, i);
                    }
                }
            ''',
            dependencies=[eval_function_info])

        simulate_function.evaluate(kernel_data, parameters.shape[0])
        return kernel_data['estimates'].get_data()
コード例 #10
0
def _resolve_model_prior(prior, model_parameters):
    """Resolve the model priors.

    Args:
        prior (None or str or mot.lib.cl_function.CLFunction): the prior defined in the composite model template.
        model_parameters (str): the (model, parameter) tuple for all the parameters in the model

    Returns:
        list of mdt.model_building.utils.ModelPrior: list of model priors
    """
    if prior is None:
        return []

    if isinstance(prior, CLFunction):
        return [prior]

    dotted_names = ['{}.{}'.format(m.name, p.name) for m, p in model_parameters]
    dotted_names.sort(key=len, reverse=True)

    parameters = []
    remaining_prior = prior
    for dotted_name in dotted_names:
        bar_name = dotted_name.replace('.', '_')

        if dotted_name in remaining_prior:
            prior = prior.replace(dotted_name, bar_name)
            remaining_prior = remaining_prior.replace(dotted_name, '')
            parameters.append('mot_float_type ' + dotted_name)
        elif bar_name in remaining_prior:
            remaining_prior = remaining_prior.replace(bar_name, '')
            parameters.append('mot_float_type ' + dotted_name)

    return [SimpleCLFunction('mot_float_type', 'model_prior', parameters, prior)]
コード例 #11
0
def _derivation_kernel(objective_func, nmr_params, nmr_steps, step_ratio,
                       parameter_transform_func):
    coords = [(x, y) for x, y in itertools.combinations_with_replacement(
        range(nmr_params), 2)]
    func = _get_compute_functions_cl(objective_func, nmr_params, nmr_steps,
                                     step_ratio, parameter_transform_func)

    return SimpleCLFunction.from_string('''
        void compute(local mot_float_type* parameters,
                     global float* parameter_scalings_inv,
                     global float* initial_step,
                     global double* step_evaluates,
                     void* data){
                                 
            double f_x_input = _calculate_function(data, parameters);
            
            uint coords[''' + str(len(coords)) + '''][2] = {
                ''' + ', '.join('{{{}, {}}}'.format(*c) for c in coords) + '''
            };
            
            for(uint coord_ind = 0; coord_ind < ''' + str(len(coords)) +
                                        '''; coord_ind++){
                _compute_steps(data, parameters, f_x_input, coords[coord_ind][0], coords[coord_ind][1], 
                               step_evaluates + coord_ind * ''' +
                                        str(nmr_steps) +
                                        ''', parameter_scalings_inv,
                               initial_step);
            }
        }
    ''',
                                        cl_extra=func)
コード例 #12
0
def _resolve_prior(prior, compartment_name, compartment_parameters):
    """Create a proper prior out of the given prior information.

    Args:
        prior (str or mot.lib.cl_function.CLFunction or None):
            The prior from which to construct a prior.
        compartment_name (str): the name of the compartment
        compartment_parameters (list of str): the list of parameters of this compartment, used
            for looking up the used parameters in a string prior

    Returns:
        List[mdt.models.compartments.CompartmentPrior]: the list of extra priors for this compartment
    """
    if prior is None:
        return []

    if isinstance(prior, CLFunction):
        return [prior]

    parameters = [
        'mot_float_type ' + p for p in compartment_parameters if p in prior
    ]
    return [
        SimpleCLFunction('mot_float_type', 'prior_' + compartment_name,
                         parameters, prior)
    ]
コード例 #13
0
ファイル: utils.py プロジェクト: iPadawan/MDT
    def encode_decode(self,
                      parameters,
                      kernel_data=None,
                      cl_runtime_info=None):
        """First apply an encoding operation and then apply a decoding operation again.

        This can be used to enforce boundary conditions in the parameters.

        Args:
            parameters (ndarray): The parameters to transform
            kernel_data (dict[str: mot.lib.utils.KernelData]): the additional data to load
            cl_runtime_info (mot.configuration.CLRuntimeInfo): the runtime information

        Returns:
            ndarray: The array with the transformed parameters.
        """
        encode_func = self.get_encode_function()
        decode_func = self.get_decode_function()

        func = SimpleCLFunction.from_string(
            '''
            void encode_decode_parameters(void* data, local mot_float_type* x){
                ''' + encode_func.get_cl_function_name() + '''(data, x);
                ''' + decode_func.get_cl_function_name() + '''(data, x);
            }
        ''',
            dependencies=[encode_func, decode_func])
        return self._transform_parameters(func,
                                          parameters,
                                          kernel_data,
                                          cl_runtime_info=cl_runtime_info)
コード例 #14
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})
コード例 #15
0
ファイル: base.py プロジェクト: EricHughesABC/MOT
 def __init__(self, cl_code, **kwargs):
     func = SimpleCLFunction.from_string(cl_code, **kwargs)
     super().__init__(func.get_return_type(),
                      func.get_cl_function_name(),
                      func.get_parameters(),
                      func.get_cl_body(),
                      dependencies=func.get_dependencies(),
                      cl_extra=func.get_cl_extra())
コード例 #16
0
def _get_numdiff_hessian_element_func(objective_func, nmr_steps, step_ratio):
    """Return a function to compute one element of the Hessian matrix."""
    return SimpleCLFunction.from_string(
        '''
        /**
         * Compute the Hessian using (possibly) multiple steps with various interpolations.
         */
        void _numdiff_hessian_element(
                void* data, local mot_float_type* x_tmp, mot_float_type f_x_input,
                uint px, uint py, global float* initial_step, global double* derivative,
                global double* error, local double* scratch){

            const uint nmr_steps = ''' + str(nmr_steps) + ''';
            uint nmr_steps_remaining = nmr_steps;

            local double* scratch_ind = scratch;
            local double* steps = scratch_ind;      scratch_ind += nmr_steps;
            local double* errors = scratch_ind;     scratch_ind += nmr_steps - 1;
            local double* steps_tmp = scratch_ind;  scratch_ind += nmr_steps;

            if(get_local_id(0) == 0){
                for(int i = 0; i < nmr_steps - 1; i++){
                    errors[i] = 0;
                }
            }
            barrier(CLK_LOCAL_MEM_FENCE);

            _numdiff_hessian_steps(data, x_tmp, f_x_input, px, py, steps, initial_step);

            if(nmr_steps_remaining > 1){
                nmr_steps_remaining = _numdiff_hessian_richardson_extrapolation(steps);
                barrier(CLK_LOCAL_MEM_FENCE);
            }

            if(nmr_steps_remaining >= 3){
                nmr_steps_remaining = _numdiff_wynn_extrapolation(steps, errors, nmr_steps_remaining);
                barrier(CLK_LOCAL_MEM_FENCE);
            }

            if(nmr_steps_remaining > 1){
                _numdiff_find_best_step(steps, errors, steps_tmp, nmr_steps_remaining);
                barrier(CLK_LOCAL_MEM_FENCE);
            }

            if(get_local_id(0) == 0){
                *derivative = steps[0];
                *error = errors[0];
            }
        }
    ''',
        dependencies=[
            _get_numdiff_hessian_steps_func(objective_func, nmr_steps,
                                            step_ratio),
            _get_numdiff_hessian_richardson_extrapolation_func(
                nmr_steps, step_ratio),
            _get_numdiff_wynn_extrapolation_func(),
            _get_numdiff_find_best_step_func()
        ])
コード例 #17
0
def get_log_prior_function():
    return SimpleCLFunction.from_string('''
        double germanTank_logPrior(local const mot_float_type* const x, void* data){
            uint nmr_tanks = (uint)round(x[0]);
            return discrete_uniform(
                nmr_tanks, ((_model_data*)data)->lower_bounds[0], ((_model_data*)data)->upper_bounds[0]);
        }
    ''',
                                        dependencies=[discrete_uniform_func()])
コード例 #18
0
def discrete_uniform_func():
    return SimpleCLFunction.from_string('''
        float discrete_uniform(uint x, uint lower, uint upper){
            if(x < lower || x > upper){
                return -INFINITY;
            }
            return -log((float)(upper-lower));
        }
    ''')
コード例 #19
0
ファイル: __init__.py プロジェクト: vishalbelsare/MOT
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})
コード例 #20
0
def maximize(func, x0, nmr_observations, **kwargs):
    """Maximization of a function.

    This wraps the objective function to take the negative of the computed values and passes it then on to one
    of the minimization routines.

    Args:
        func (mot.lib.cl_function.CLFunction): A CL function with the signature:

            .. code-block:: c

                double <func_name>(local const mot_float_type* const x,
                                   void* data,
                                   local mot_float_type* objective_list);

            The objective list needs to be filled when the provided pointer is not null. It should contain
            the function values for each observation. This list is used by non-linear least-squares routines,
            and will be squared by the least-square optimizer. This is only used by the ``Levenberg-Marquardt`` routine.

        x0 (ndarray): Initial guess. Array of real elements of size (n, p), for 'n' problems and 'p'
            independent variables.
        nmr_observations (int): the number of observations returned by the optimization function.
        **kwargs: see :func:`minimize`.
    """
    wrapped_func = SimpleCLFunction.from_string(
        '''
        double _negate_''' + func.get_cl_function_name() + '''(
                local mot_float_type* x,
                void* data, 
                local mot_float_type* objective_list){

            double return_val = ''' + func.get_cl_function_name() +
        '''(x, data, objective_list);    

            if(objective_list){
                const uint nmr_observations = ''' + str(nmr_observations) +
        ''';
                uint local_id = get_local_id(0);
                uint workgroup_size = get_local_size(0);

                uint observation_ind;
                for(uint i = 0; i < (nmr_observations + workgroup_size - 1) / workgroup_size; i++){
                    observation_ind = i * workgroup_size + local_id;

                    if(observation_ind < nmr_observations){
                        objective_list[observation_ind] *= -1;    
                    }
                }
            }
            return -return_val;
        }
    ''',
        dependencies=[func])
    kwargs['nmr_observations'] = nmr_observations
    return minimize(wrapped_func, x0, **kwargs)
コード例 #21
0
    def get_cl_function():
        nmr_params = parameters.shape[1]

        if len(parameters.shape) > 2:
            return SimpleCLFunction.from_string(
                '''
                void compute(global mot_float_type* parameters, 
                             global mot_float_type* log_likelihoods,
                             void* data){
                             
                    local mot_float_type x[''' + str(nmr_params) + '''];

                    for(uint sample_ind = 0; sample_ind < ''' +
                str(parameters.shape[2]) + '''; sample_ind++){
                        for(uint i = 0; i < ''' + str(nmr_params) + '''; i++){
                            x[i] = parameters[i *''' +
                str(parameters.shape[2]) + ''' + sample_ind];
                        }
                        
                        double ll = ''' + ll_func.get_cl_function_name() +
                '''(x, data);
                        if(get_local_id(0) == 0){
                            *(log_likelihoods) = ll;
                        }
                    }
                }
            ''',
                dependencies=[ll_func])

        return SimpleCLFunction.from_string('''
            void compute(local mot_float_type* parameters, 
                         global mot_float_type* log_likelihoods,
                         void* data){
                         
                double ll = ''' + ll_func.get_cl_function_name() +
                                            '''(parameters, data);
                if(get_local_id(0) == 0){
                    *(log_likelihoods) = ll;
                }
            }
        ''',
                                            dependencies=[ll_func])
コード例 #22
0
ファイル: random.py プロジェクト: EricHughesABC/MOT
def uniform(nmr_distributions,
            nmr_samples,
            low=0,
            high=1,
            ctype='float',
            seed=None):
    """Draw random samples from the Uniform distribution.

    Args:
        nmr_distributions (int): the number of unique continuous_distributions to create
        nmr_samples (int): The number of samples to draw
        low (double): The minimum value of the random numbers
        high (double): The minimum value of the random numbers
        ctype (str): the C type of the output samples
        seed (float): the seed for the RNG

    Returns:
        ndarray: A two dimensional numpy array as (nmr_distributions, nmr_samples).
    """
    if is_scalar(low):
        low = np.ones((nmr_distributions, 1)) * low
    if is_scalar(high):
        high = np.ones((nmr_distributions, 1)) * high

    kernel_data = {
        'low': Array(low, as_scalar=True),
        'high': Array(high, as_scalar=True)
    }

    kernel = SimpleCLFunction.from_string(
        '''
        void compute(double low, double high, global uint* rng_state, global '''
        + ctype + '''* samples){
        
            rand123_data rand123_rng_data = rand123_initialize_data((uint[]){
                rng_state[0], rng_state[1], rng_state[2], rng_state[3], 
                rng_state[4], rng_state[5], 0});
            void* rng_data = (void*)&rand123_rng_data;

            for(uint i = 0; i < ''' + str(nmr_samples) + '''; i++){
                double4 randomnr = rand4(rng_data);
                samples[i] = (''' + ctype +
        ''')(low + randomnr.x * (high - low));
            }
        }
    ''',
        dependencies=[Rand123()])

    return _generate_samples(kernel,
                             nmr_distributions,
                             nmr_samples,
                             ctype,
                             kernel_data,
                             seed=seed)
コード例 #23
0
def get_log_prior_function(nmr_parameters):
    return SimpleCLFunction.from_string('''
        double rosenbrock_logPrior(local const mot_float_type* const x, void* data){
            for(uint i = 0; i < ''' + str(nmr_parameters) + '''; i++){
                if(x[i] < -10 || x[i] > 10){
                    return log(0.0);
                }
            }
            return log(1.0);
        }
    ''')
コード例 #24
0
    def _transform_parameters(cl_func, parameters, kernel_data, cl_runtime_info=None):
        cl_named_func = SimpleCLFunction.from_string('''
            void transformParameterSpace(void* data, local mot_float_type* x){
                ''' + cl_func.get_cl_function_name() + '''(data, x);
            }
        ''', dependencies=[cl_func])

        kernel_data = {'data': kernel_data,
                       'x': Array(parameters, ctype='mot_float_type', mode='rw')}

        cl_named_func.evaluate(kernel_data, parameters.shape[0], cl_runtime_info=cl_runtime_info)
        return kernel_data['x'].get_data()
コード例 #25
0
def _richardson_error_kernel(nmr_steps, nmr_convolutions,
                             richardson_coefficients):
    func = _get_error_estimate_functions_cl(nmr_steps, nmr_convolutions,
                                            richardson_coefficients)

    return SimpleCLFunction.from_string('''
        void convolute(global double* derivatives, global double* richardson_extrapolations, global double* errors){
            _apply_richardson_convolution(derivatives, richardson_extrapolations);
            _compute_richardson_errors(derivatives, richardson_extrapolations, errors);
        }
    ''',
                                        cl_extra=func)
コード例 #26
0
def get_log_likelihood_function(nmr_parameters):
    return SimpleCLFunction.from_string('''
        double rosenbrock_logLikelihood(local const mot_float_type* const x, void* data){
            double sum = 0;
            double eval;
            for(uint i = 0; i < ''' + str(nmr_parameters) + ''' - 1; i++){
                eval = -(100 * pown(x[i + 1] - pown(x[i], 2), 2) + pown(1 - x[i], 2));
                sum += eval;
            }
            return sum;
        }
    ''')
コード例 #27
0
ファイル: __init__.py プロジェクト: vishalbelsare/MOT
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})
コード例 #28
0
ファイル: random.py プロジェクト: EricHughesABC/MOT
def normal(nmr_distributions,
           nmr_samples,
           mean=0,
           std=1,
           ctype='float',
           seed=None):
    """Draw random samples from the Gaussian distribution.

    Args:
        nmr_distributions (int): the number of unique continuous_distributions to create
        nmr_samples (int): The number of samples to draw
        mean (float or ndarray): The mean of the distribution
        std (float or ndarray): The standard deviation or the distribution
        ctype (str): the C type of the output samples
        seed (float): the seed for the RNG

    Returns:
        ndarray: A two dimensional numpy array as (nmr_distributions, nmr_samples).
    """
    if is_scalar(mean):
        mean = np.ones((nmr_distributions, 1)) * mean
    if is_scalar(std):
        std = np.ones((nmr_distributions, 1)) * std

    kernel_data = {
        'mean': Array(mean, as_scalar=True),
        'std': Array(std, as_scalar=True)
    }

    kernel = SimpleCLFunction.from_string('''
        void compute(double mean, double std, global uint* rng_state, global '''
                                          + ctype + '''* samples){
            rand123_data rand123_rng_data = rand123_initialize_data((uint[]){
                rng_state[0], rng_state[1], rng_state[2], rng_state[3], 
                rng_state[4], rng_state[5], 0});
            void* rng_data = (void*)&rand123_rng_data;

            for(uint i = 0; i < ''' + str(nmr_samples) + '''; i++){
                double4 randomnr = randn4(rng_data);
                samples[i] = (''' + ctype + ''')(mean + randomnr.x * std);
            }
        }
    ''',
                                          dependencies=[Rand123()])

    return _generate_samples(kernel,
                             nmr_distributions,
                             nmr_samples,
                             ctype,
                             kernel_data,
                             seed=seed)
コード例 #29
0
ファイル: base.py プロジェクト: vishalbelsare/MOT
    def _initialize_likelihood_prior(self, positions, log_likelihoods,
                                     log_priors):
        """Initialize the likelihood and the prior using the given positions.

        This is a general method for computing the log likelihoods and log priors for given positions.

        Subclasses can use this to instantiate secondary chains as well.
        """
        func = SimpleCLFunction.from_string(
            '''
            void compute(global mot_float_type* chain_position,
                         global mot_float_type* log_likelihood,
                         global mot_float_type* log_prior,
                         local mot_float_type* x_tmp,
                         void* data){

                bool is_first_work_item = get_local_id(0) == 0;

                if(is_first_work_item){
                    for(uint i = 0; i < ''' + str(self._nmr_params) +
            '''; i++){
                        x_tmp[i] = chain_position[i];
                    }
                    *log_prior = _computeLogPrior(x_tmp, data);
                }
                barrier(CLK_LOCAL_MEM_FENCE);

                *log_likelihood = _computeLogLikelihood(x_tmp, data);
            }
        ''',
            dependencies=[
                self._get_log_prior_cl_func(),
                self._get_log_likelihood_cl_func()
            ])

        kernel_data = {
            'chain_position': Array(positions, 'mot_float_type', mode='rw'),
            'log_likelihood': Array(log_likelihoods,
                                    'mot_float_type',
                                    mode='rw'),
            'log_prior': Array(log_priors, 'mot_float_type', mode='rw'),
            'x_tmp': LocalMemory('mot_float_type', self._nmr_params),
            'data': self._data
        }

        func.evaluate(kernel_data,
                      self._nmr_problems,
                      use_local_reduction=all(
                          env.is_gpu
                          for env in self._cl_runtime_info.cl_environments),
                      cl_runtime_info=self._cl_runtime_info)
コード例 #30
0
ファイル: base.py プロジェクト: 42n4/MOT
    def __init__(self,
                 ll_func,
                 log_prior_func,
                 x0,
                 proposal_stds,
                 use_random_scan=False,
                 finalize_proposal_func=None,
                 **kwargs):
        """An abstract basis for Random Walk Metropolis (RWM) samplers.

        Random Walk Metropolis (RWM) samplers require for every parameter and every modeling instance an proposal
        standard deviation, used in the random walk.

        Args:
            ll_func (mot.lib.cl_function.CLFunction): The log-likelihood function.
            log_prior_func (mot.lib.cl_function.CLFunction): The log-prior function.
            x0 (ndarray): the starting positions for the sampler. Should be a two dimensional matrix
                with for every modeling instance (first dimension) and every parameter (second dimension) a value.
            proposal_stds (ndarray): for every parameter and every modeling instance an initial proposal std.
            use_random_scan (boolean): if we iterate over the parameters in a random order or in a linear order
                at every sample iteration. By default we apply a system scan starting from the first dimension to the
                last. With a random scan we randomize the indices every iteration.
            finalize_proposal_func (mot.lib.cl_function.CLFunction): a CL function to finalize every proposal by
                the sampling routine. This allows the model to change a proposal before computing the
                prior or likelihood probabilities. If None, we will not use this callback.

                As an example, suppose you are sampling a polar coordinate :math:`\theta` defined on
                :math:`[0, 2\pi]` with a random walk Metropolis proposal distribution. This distribution might propose
                positions outside of the range of :math:`\theta`. Of course the model function could deal with that by
                taking the modulus of the input, but then you have to post-process the chain with the same
                transformation. Instead, this function allows changing the proposal before it is put into the model
                and before it will be stored in the chain.

                This function should return a proposal that is equivalent (but not necessarily equal)
                to the provided proposal.

                Signature:

                .. code-block:: c

                    void <func_name>(void* data, local mot_float_type* x);
        """
        super().__init__(ll_func, log_prior_func, x0, **kwargs)
        self._proposal_stds = np.require(
            np.copy(proposal_stds),
            requirements='CAOW',
            dtype=self._cl_runtime_info.mot_float_dtype)
        self._use_random_scan = use_random_scan
        self._finalize_proposal_func = finalize_proposal_func or SimpleCLFunction.from_string(
            'void finalizeProposal(void* data, local mot_float_type* x){}')