Main Content

Code Generation for Probability Distribution Objects

This example shows how to generate code that fits a probability distribution to sample data and evaluates the fitted distribution.

First, define an entry-point function that uses fitdist to create a probability distribution object and uses its object functions to evaluate the fitted distribution. Then, generate code for the entry-point function by using codegen (MATLAB Coder). An entry-point function can have a probability distribution object as both an input argument and an output argument. Therefore, alternatively, you can define two entry-point functions, one for fitting a distribution and the other for evaluating the fitted distribution. The first entry-point function returns a fitted distribution, and the second entry-point function accepts the fitted distribution as an input argument. This example first describes the workflow with a single entry-point function, and then briefly describes the workflow with two entry-point functions.

fitdist supports code generation for beta, exponential, extreme value, lognormal, normal, and Weibull distributions. The supported object functions of the fitted probability distribution objects, created by fitdist, are cdf, icdf, iqr, mean, median, pdf, std, truncate, and var.

For more information on code generation, see General Code Generation Workflow.

Define Entry-Point Function

Define an entry-point function named myFitandEvaluate that takes the sample data, distribution name, truncation limits of the distribution, and data values at which to evaluate the cumulative distribution function (cdf) and probability density function (pdf). Within the entry-point function, fit a probability distribution object to the sample data, truncate the distribution to the specified truncation limits, compute the mean of the truncated distribution, and compute the cdf and pdf values at the specified data values.

Display the contents of the myFitandEvaluate.m file.

type myFitandEvaluate.m
function [pd_truncated,st] = myFitandEvaluate(data,distname,truncation_limits,x) %#codegen
% Fit a probability distribution object to data.
pd = fitdist(data,distname);

% Truncate pd.
pd_truncated = truncate(pd,truncation_limits(1),truncation_limits(2));

% Compute the mean of the truncated pd.
mean_val = mean(pd_truncated);

% Compute the cdf and pdf, evaluated at x.
cdf_val = cdf(pd_truncated,x);
pdf_val = pdf(pd_truncated,x);

% Create a structure array containing the mean, cdf, and pdf values.
st = struct('mean', mean_val,'cdf',cdf_val,'pdf',pdf_val);
end

Note: If you click the button located in the upper-right section of this page and open this example in MATLAB®, then MATLAB opens the example folder. This folder includes the entry-point function files for this example.

Generate Code

Specify the input argument types of myFitandEvaluate using a 4-by-1 cell array. Assign each input argument type of the entry-point function to each cell. Specify the data type and exact input array size by using an example value that represents the set of values with a certain data type and array size.

ARGS = cell(4,1);
ARGS{1} = ones(100,1);
ARGS{2} = coder.Constant('Exponential');
ARGS{3} = ones(1,2);
ARGS{4} = ones(10,1);

The second input of myFitandEvaluate is a distribution name, which is the second input argument of fitdist. This argument must be a compile-time constant. Therefore, you specify ARGS{2} by using coder.Constant (MATLAB Coder).

If you want to specify ARGS{1} and ARGS{3} as variable-size inputs, use coder.typeof (MATLAB Coder). For details, see General Code Generation Workflow.

Generate a MEX function from the entry-point function myFitandEvaluate. Specify the input argument types using the -args option and the cell array ARGS.

codegen myFitandEvaluate -args ARGS
Code generation successful.

codegen (MATLAB Coder) generates the MEX function myFitandEvaluate_mex with a platform-dependent extension in your current folder.

Verify Generated Code

Pass some data to verify whether myFitandEvaluate and myFitandEvaluate_mex return the same outputs.

rng('default') % For reproducibility
data = exprnd(1,[100,1]); % Exponential random numbers with mean parameter 1
distname = 'Exponential';
truncation_limits = [0,4];
x = (0:9)';
[pd_truncated,st] = myFitandEvaluate(data,distname,truncation_limits,x);
[pd_truncated_mex,st_mex] = myFitandEvaluate_mex(data,distname,truncation_limits,x);

Compare the probability distribution objects pd_truncated and pd_truncated_mex.

pd_truncated
pd_truncated = 
  ExponentialDistribution

  Exponential distribution
    mu = 0.917049
  Truncated to the interval [0, 4]

pd_truncated_mex
pd_truncated_mex = 
  ExponentialDistribution

  Exponential distribution
    mu = 0.917049
  Truncated to the interval [0, 4]

verifyMEX_pd = isequal(pd_truncated,pd_truncated_mex)
verifyMEX_pd = logical
   1

isequal returns logical 1 (true), which means pd_truncated and pd_truncated_mex are equal.

Compare the structure arrays that contain the mean, cdf, and pdf values.

verifyMEX_st = isequal(st,st_mex)
verifyMEX_st = logical
   1

The comparison confirms that myFitandEvaluate and myFitandEvaluate_mex return the same outputs. The generated code might not produce the same floating-point numerical results as MATLAB, as described in Differences Between Generated Code and MATLAB Code (MATLAB Coder). In that case, compare the values allowing a small tolerance.

Workflow with Two Entry-Point Functions

An entry-point function can have a probability distribution object as both an input argument and an output argument. Therefore, you can define two entry-point functions, one for fitting a distribution and the other for evaluating the fitted distribution. Then generate code for the two entry-point functions.

Define Entry-Point Functions

Define two entry-point functions. The first entry-point function myFitDist fits a probability distribution object to the sample data. The second entry-point function myEvaluateDist truncates the distribution, computes the mean of the truncated distribution, and computes the cdf and pdf values at the specified data values. myEvaluateDist takes the output of myFitDist as an input argument.

Display the contents of the myFitDist.m and myEvaluateDist.m files.

type myFitDist.m
function pd = myFitDist(data,dist) %#codegen
% Fit probability distribution object to data.
pd = fitdist(data,dist);
end
type myEvaluateDist.m
function [pd_truncated,st] = myEvaluateDist(pd,truncation_limits,x) %#codegen
% Truncate pd.
pd_truncated = truncate(pd,truncation_limits(1),truncation_limits(2));

% Compute the mean of the truncated pd.
mean_val = mean(pd_truncated);

% Compute the cdf and pdf, evaluated at x.
cdf_val = cdf(pd_truncated,x);
pdf_val = pdf(pd_truncated,x);

% Create a structure array containing the mean, cdf, and pdf values.
st = struct('mean', mean_val,'cdf',cdf_val,'pdf',pdf_val);
end

Generate Code

Specify the input argument types of myFitDist and myEvaluateDist.

ARGS_myFitDist = cell(2,1);
ARGS_myFitDist{1} = ones(100,1);
ARGS_myFitDist{2} = coder.Constant('Exponential');

ARGS_myEvaluateDist = cell(3,1);
ARGS_myEvaluateDist{1} = fitdist(exprnd(1,[100,1]),'Exponential');
ARGS_myEvaluateDist{2} = ones(1,2); 
ARGS_myEvaluateDist{3} = ones(10,1);

If you do not need to generate a MEX function, then you can specify ARGS_myEvaluateDist{1} as coder.OutputType('myFitdist'), as described in Pass an Entry-Point Function Output as an Input (MATLAB Coder). You cannot use coder.OutputType (MATLAB Coder) when generating a MEX function, because the data type of the output from myFitDist does not match the data type of the input to myEvaluateDist in the generated MEX function.

Generate code for the two entry-point functions.

codegen -o myFitandEvaluate_mex2 myFitDist -args ARGS_myFitDist myEvaluateDist -args ARGS_myEvaluateDist
Code generation successful.

codegen (MATLAB Coder) generates the MEX function myFitandEvaluate_mex2. For details about generating code for multiple entry-point functions, see Generate Code for Multiple Entry-Point Functions (MATLAB Coder).

Verify Generated Code

Verify the generated code.

rng('default') 
data = exprnd(1,[100,1]);
distname = 'Exponential';
truncation_limits = [0,4];
x = (0:9)';
pd2 = myFitDist(data,distname);
[pd_truncated2,st2] = myEvaluateDist(pd2,truncation_limits,x);
pd_mex2 = myFitandEvaluate_mex2('myFitDist',data,distname);
[pd_truncated_mex2,st_mex2] = myFitandEvaluate_mex2('myEvaluateDist',pd_mex2,truncation_limits,x);
verifyMEX_pd2 = isequal(pd2,pd_mex2)
verifyMEX_pd2 = logical
   1

verifyMEX_pd_truncated2 = isequal(pd_truncated2,pd_truncated_mex)
verifyMEX_pd_truncated2 = logical
   1

verifyMEX_st2 = isequal(st2,st_mex2)
verifyMEX_st2 = logical
   1

isequal returns logical 1 (true), which means that the entry-point functions and the corresponding MEX functions return the same outputs.

See Also

(MATLAB Coder) | | | | | | |

Related Topics