ans =
solve() returning empty, does a solution exist?
Show older comments
Hey all. For a project I'm doing, I need to generate a random number from a custom probability density function. To do that, I am generating a random number using rand, and finding its corresponding y-value on the related cumulative distribution function. However, solve() and vpasolve() only seem to return answers for some of these random values. Looking at the graph of this function, however, it would seem that these values exist. The relevant code, as well as the cumulative distribution function Fx, are below. Is it possible that my cumulative distribution function is too complicated, or that a solution doesn't exist after all? Any help would be greatly appreciated! Also, I am new to Matlab, so apologies if my code contains rookie mistakes!

clear all;
%Define the mean and standard deviation of the target normal distribution
%curve.
mu = 130;
stdev = 5/2;
%Define the function whose input is being tested (fy), as well as the target
%normal distribution PDF (normdist).
syms x p t;
fy(x) = (-0.003867*x^3 + 0.01413*x^2 + 3.742*x + 101.9);
normdist(p) = (1/(sqrt(2*pi*(stdev)^2))*exp(-(p - mu)^2/(2*(stdev)^2)));
%Create PDF of x (fx)
fx(x) = (normdist(fy) * abs(diff(fy)));
%Temp fx function in terms of t for integrating
fxtemp(t) = fx(t);
%Create CDF of x (Fx)
%Determine integral bounds (if fy is not monotonic)
localextrema_xvals = vpasolve(diff(fy) == 0, x);
localextrema_yvals = fy(localextrema_xvals);
localmin = [localextrema_xvals(1) localextrema_yvals(1)];
localmax = [localextrema_xvals(2) localextrema_yvals(2)];
localmin_xints = vpasolve(fy == localmin(2), x, [-50 50]);
localmax_xints = vpasolve(fy == localmax(2), x, [-50, 50]);
interval1ub = localmax_xints(1);
interval3lb = localmin_xints;
%Set up function (piecewise if necessary)
interval1 = int(fxtemp, t, -Inf, interval1ub);
interval2 = int(fxtemp, t, localmin(1), localmax(1));
Fx(x) = piecewise(x < interval1ub, int(fxtemp, t, -Inf, x), ...
(x >= localmin(1)) & (x <= localmax(1)), interval1 + int(fxtemp, t, localmin(1), x),...
x > interval3lb, interval1 + interval2 + int(fxtemp, t, interval3lb, x));
%Example of solve that cannot be done
xval = solve(Fx == 0.0284, x);
% %Generate 10000 random x values via inverse CDF method, not working!
% randvals = rand(10000, 1);
% xvals = zeros(10000, 1, "sym");
% for i = 1:10000
% xvals(i) = solve(Fx == randvals(i), x);
% end
% yvals = fy(xvals);
% yvals = double(yvals);
2 Comments
For the second part of problem, use subs function to evaluate the function at different x values
clear all;
%Define the mean and standard deviation of the target normal distribution
%curve.
mu = 130;
stdev = 5/2;
%Define the function whose input is being tested (fy), as well as the target
%normal distribution PDF (normdist).
syms x p t;
fy(x) = (-0.003867*x^3 + 0.01413*x^2 + 3.742*x + 101.9);
normdist(p) = (1/(sqrt(2*pi*(stdev)^2))*exp(-(p - mu)^2/(2*(stdev)^2)));
%Create PDF of x (fx)
fx(x) = (normdist(fy) * abs(diff(fy)));
%Temp fx function in terms of t for integrating
fxtemp(t) = fx(t);
%Create CDF of x (Fx)
%Determine integral bounds (if fy is not monotonic)
localextrema_xvals = vpasolve(diff(fy) == 0, x);
localextrema_yvals = fy(localextrema_xvals);
localmin = [localextrema_xvals(1) localextrema_yvals(1)];
localmax = [localextrema_xvals(2) localextrema_yvals(2)];
localmin_xints = vpasolve(fy == localmin(2), x, [-50 50]);
localmax_xints = vpasolve(fy == localmax(2), x, [-50, 50]);
interval1ub = localmax_xints(1);
interval3lb = localmin_xints;
%Set up function (piecewise if necessary)
interval1 = int(fxtemp, t, -Inf, interval1ub);
interval2 = int(fxtemp, t, localmin(1), localmax(1));
Fx(x) = piecewise(x < interval1ub, int(fxtemp, t, -Inf, x), ...
(x >= localmin(1)) & (x <= localmax(1)), interval1 + int(fxtemp, t, localmin(1), x),...
x > interval3lb, interval1 + interval2 + int(fxtemp, t, interval3lb, x));
%Example of solve that cannot be done
xval = solve(Fx == 0.0284,x);
% %Generate 10000 random x values via inverse CDF method, not working!
randvals = rand(10, 1);
for i = 1:10
xvals{i} = solve(Fx == randvals(i), x);
yvals{i} = double(subs(fy,x,xvals{i}));
end
yvals{:}
Before getting to the inverse sampling, we have to make sure the underlying pdf and cdf are correct.
Here is the original code, with slight modifications to enforce sym as much as possible
mu = sym(130);
stdev = sym(5)/sym(2);
%Define the function whose input is being tested (fy), as well as the target
%normal distribution PDF (normdist).
syms x p t;
fy(x) = (-0.003867*x^3 + 0.01413*x^2 + 3.742*x + 101.9);
normdist(p) = (1/(sqrt(2*sym(pi)*(stdev)^2))*exp(-(p - mu)^2/(2*(stdev)^2)));
%Create PDF of x (fx)
fx(x) = (normdist(fy) * abs(diff(fy)));
fx(x) cannot be a pdf because it doesn't integrate to unity
int(fx(x),x,-inf,inf)
vpa(ans)
Maybe fx(x) as defined should be divided by 3?
Given that fx(x) is defined as it is, there doesn't seem to be a reason for the piecewise manipulations. int works fine; it returns a piecewise expression on its own.
F1x(x) = int(fx(t),t,-inf,x);
vpa(F1x(x),5)
Here is original code
%Temp fx function in terms of t for integrating
fxtemp(t) = fx(t);
%Create CDF of x (Fx)
%Determine integral bounds (if fy is not monotonic)
localextrema_xvals = vpasolve(diff(fy) == 0, x);
localextrema_yvals = fy(localextrema_xvals);
localmin = [localextrema_xvals(1) localextrema_yvals(1)];
localmax = [localextrema_xvals(2) localextrema_yvals(2)];
localmin_xints = vpasolve(fy == localmin(2), x, [-50 50]);
localmax_xints = vpasolve(fy == localmax(2), x, [-50, 50]);
interval1ub = localmax_xints(1);
interval3lb = localmin_xints;
%Set up function (piecewise if necessary)
interval1 = int(fxtemp, t, -Inf, interval1ub);
interval2 = int(fxtemp, t, localmin(1), localmax(1));
Fx(x) = piecewise(x < interval1ub, int(fxtemp, t, -Inf, x), ...
(x >= localmin(1)) & (x <= localmax(1)), interval1 + int(fxtemp, t, localmin(1), x),...
x > interval3lb, interval1 + interval2 + int(fxtemp, t, interval3lb, x));
vpa(Fx(x),5)
We see that Fx is not defined over two regions and returns NaN when evaluated in those regions
Fx([-20,20])
At least the limit of Fx(x) -> 1, as it should if it were a cdf
limit(Fx(x),x,inf)
Comparison shows quite a difference, even after normalizing F1
figure
fplot([Fx(x),F1x(x)/3],[-50,50])
Perhaps it would be helpful to explain in mathematical terms what the problem actually is.
Accepted Answer
More Answers (0)
Categories
Find more on Calculus in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!





