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
codegen
(MATLAB Coder) | fitdist
| BetaDistribution
| ExponentialDistribution
| ExtremeValueDistribution
| LognormalDistribution
| NormalDistribution
| WeibullDistribution