Clear Filters
Clear Filters

How to fill a variable with the results of an if...elseif statement

5 views (last 30 days)
I am trying to apply the second derivative test to a function and find all the relative maxima, minima, saddlepoints, and inconclusive results from the function's critical points. I think I have my code where I want it, but my fmin, fmax, and saddlePts should have more than just one point (x,y) stored. I'm quite sure that each time a condition is met in the if...elseif statement, that the previous point store is getting overwritten, which results in just last indice to meet the criteria being stored.
How can I get all the 9 points to be stored properly in the if...elseif statement? I.e. How to a prevent the overwriting, and allow fmin, fmax, and saddlePts to be filled with more than one point?
% Using MATLAB, find and evaluate all maxima, minima, and saddle points of
% the function f(x,y)= x*y*(x^2+y^2-2.56).
clear
clc
syms x y % Initiate SYMBOLIC MATH
% Find fist-order partial derivative: fx and fy.
f(x,y)= x*y*(x^2+y^2-2.56);
fx = simplify(diff(f,x)); fy = simplify(diff(f,y));
% Set fx and fy equal to zero and solve for critical points. Save x and y
% values as xcrit and ycrit.
S = solve(fx,fy);
xcrit = S.x; ycrit = S.y;
% Find second-order partial derivatives: fxx, fyy, and fxy.
fxx = simplify(diff(fx,x));
fyy = simplify(diff(fy,y));
fxy = simplify(diff(fx,y));
% Perform a second-order derivative test of each critical point. Label and
% store all maximum, minimum, and saddle points based on criteria:
% If D>0 and fxx(Xc,Yc)>0, then f has a relative minimum at (Xc,Yc).
% If D>0 and fxx(Xc,Yc)>0, then f has a relative maximum at (Xc,Yc).
% If D<0, then f has a saddle point at (Xc,Yc).
% If D=0, then the test is inconclusive.
% Minimums are store as fmin, maximums as fmax, saddle points as saddlePts,
% and inconclusives as inconcl.
Xc = double(xcrit); Yc = double(ycrit);
for ind = 1:9
D=fxx(Xc(ind),Yc(ind))*fyy(Xc(ind),Yc(ind)) - (fxy(Xc(ind),Yc(ind)))^2;
if D > 0 && fxx(Xc(ind),Yc(ind)) > 0
fmin = [Xc(ind) Yc(ind)];
elseif (D > 0) && (fxx(Xc(ind),Yc(ind)) < 0)
fmax = [Xc(ind) Yc(ind)];
elseif (D < 0)
saddlePts = [Xc(ind) Yc(ind)];
elseif (D == 0)
inconcl = [Xc(ind) Yc(ind)];
end
end
% Print relative minimums and maximums, saddle points, and inconclusives.
L = exist('fmin'); K = exist('fmax'); H = exist('saddlePts');
G = exist('inconcl');
fprintf('f(x,y) = %s\n\n', simplify(f));
disp('f has a relative minimum at the following points:');
if (L ~= 0)
disp(array2table(fmin, 'VariableNames', {'x', 'y'})); disp(' ');
else
disp('None'); disp(' ');
end
disp('f has a relative maximum at the following points:');
if (K ~= 0)
disp(array2table(fmax, 'VariableNames', {'x', 'y'})); disp(' ');
else
disp('None'); disp(' ');
end
disp('f has a saddle point at the following points:');
if (H~=0)
disp(array2table(saddlePts, 'VariableNames', {'x', 'y'})); disp(' ');
else
disp('None'); disp(' ');
end
disp('The 2nd derivative test was inconclusive for the following points:');
if (G ~=0)
disp(array2table(inconcl, 'VariableNames', {'x', 'y'})); disp(' ');
else
disp('None');
end

Accepted Answer

Torsten
Torsten on 1 Oct 2024
Edited: Torsten on 1 Oct 2024
Use
imin = 0;
imax = 0;
isaddlePts = 0;
iinconcl = 0;
for ind = 1:9
D=fxx(Xc(ind),Yc(ind))*fyy(Xc(ind),Yc(ind)) - (fxy(Xc(ind),Yc(ind)))^2;
if D > 0 && fxx(Xc(ind),Yc(ind)) > 0
imin = imin + 1;
fmin(imin,:) = [Xc(ind) Yc(ind)];
elseif (D > 0) && (fxx(Xc(ind),Yc(ind)) < 0)
imax = imax + 1;
fmax(imax,:) = [Xc(ind) Yc(ind)];
elseif (D < 0)
isaddlePts = isaddlePts + 1;
saddlePts(isaddlePts,:) = [Xc(ind) Yc(ind)];
elseif (D == 0)
iinconcl = iinconcl + 1;
inconcl(iinconcl,:) = [Xc(ind) Yc(ind)];
end
end
  1 Comment
Aaron
Aaron on 1 Oct 2024
Thank you for your response. Your suggestion helped fix the issue. Better still, it makes sense to me now why my code was not generated the expected results and why your suggestion fixes the issue. Have great day.

Sign in to comment.

More Answers (1)

Steven Lord
Steven Lord on 1 Oct 2024
Rather than creating variables whose number of rows is not known ahead of time, I'd consider creating a table of coordinates and have one or more variables in that table indicating what it is.
% Using MATLAB, find and evaluate all maxima, minima, and saddle points of
% the function f(x,y)= x*y*(x^2+y^2-2.56).
syms x y % Initiate SYMBOLIC MATH
% Find fist-order partial derivative: fx and fy.
f(x,y)= x*y*(x^2+y^2-2.56);
fx = simplify(diff(f,x)); fy = simplify(diff(f,y));
% Set fx and fy equal to zero and solve for critical points. Save x and y
% values as xcrit and ycrit.
S = solve(fx,fy);
xcrit = S.x; ycrit = S.y;
% Find second-order partial derivatives: fxx, fyy, and fxy.
fxx = simplify(diff(fx,x));
fyy = simplify(diff(fy,y));
fxy = simplify(diff(fx,y));
% Perform a second-order derivative test of each critical point. Label and
% store all maximum, minimum, and saddle points based on criteria:
% If D>0 and fxx(Xc,Yc)>0, then f has a relative minimum at (Xc,Yc).
% If D>0 and fxx(Xc,Yc)>0, then f has a relative maximum at (Xc,Yc).
% If D<0, then f has a saddle point at (Xc,Yc).
% If D=0, then the test is inconclusive.
% Minimums are store as fmin, maximums as fmax, saddle points as saddlePts,
% and inconclusives as inconcl.
Xc = double(xcrit); Yc = double(ycrit);
results = table('Size', [numel(Xc), 3], ...
'VariableTypes', ["sym", "sym", "string"], ...
'VariableNames', ["X", "Y", "type"]);
results.X = xcrit(:);
results.Y = ycrit(:);
% generalize the loop to handle case where xcrit/ycrit have different
% numbers of elements, using numel(Xc) instead of hard-coding 9
for ind = 1:numel(Xc)
D=fxx(Xc(ind),Yc(ind))*fyy(Xc(ind),Yc(ind)) - (fxy(Xc(ind),Yc(ind)))^2;
if D > 0 && fxx(Xc(ind),Yc(ind)) > 0
results.type(ind) = "min";
elseif (D > 0) && (fxx(Xc(ind),Yc(ind)) < 0)
results.type(ind) = "max";
elseif (D < 0)
results.type(ind) = "saddle";
elseif (D == 0) % May be able to just use "else" instead of "elseif (D==0)"
results.type(ind) = "inconclusive";
end
end
disp(results)
X Y type ____ ____ ________ 0 0 "saddle" -8/5 0 "saddle" 8/5 0 "saddle" 0 -8/5 "saddle" 0 8/5 "saddle" -4/5 -4/5 "min" 4/5 -4/5 "max" -4/5 4/5 "max" 4/5 4/5 "min"
Then if you needed to do anything with points of a certain type:
minima = results(results.type == "min", :)
minima = 2x3 table
X Y type ____ ____ _____ -4/5 -4/5 "min" 4/5 4/5 "min"
You could also have individual variables in the table if you want to have booleans to work with.
results.min = results.type == "min";
results.max = results.type == "max";
results.saddle = results.type == "saddle";
results.inconclusive = results.type == "inconclusive";
disp(results)
X Y type min max saddle inconclusive ____ ____ ________ _____ _____ ______ ____________ 0 0 "saddle" false false true false -8/5 0 "saddle" false false true false 8/5 0 "saddle" false false true false 0 -8/5 "saddle" false false true false 0 8/5 "saddle" false false true false -4/5 -4/5 "min" true false false false 4/5 -4/5 "max" false true false false -4/5 4/5 "max" false true false false 4/5 4/5 "min" true false false false

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!