My code wont run, keep getting error "Not enough input arguments"
Mostra commenti meno recenti
The following is my code for secant method optimization search. I have my objective function in one file called f.m and the algorithm in another named secant.m. Whenever I run my code I keep getting an error: Not enough input arguments. I am using MATLAB 2019b
Additionlly, could someone please let me know if the logic of my code is correct? after many iterations I should reach a value z which minimizes my function and I would like to take all the "z"s that were calculated each iteration and calculate an error and then plot those error values per iteration as my y axis and iteration on the x axis to get my graph. If someone if familiar with the secant method could you please let me know if this is correct? Thanks alot.
code in f.m file:
function g = f(x)
g = 2*((x-3)^2)+exp(0.5*x^2);
code in secant.m file:
f_prime = diff(f);
a = 0;
b = 3;
epsilon = 0.0001;
x1 = a;
x2 = b;
k = 0;
iteration = 100;
f1 = f_prime(x1);
f2 = f_prime(x2);
z = x1 - (f1/((f1-f2)*(x1-x2)));
f3 = f_prime(z);
while (abs(f3) > epsilon) && (k<iteration)
k = k+1;
if (f1>f2)
x2 = z;
z = x1 - (f1/((f1-f2)*(x1-x2)));
f3 = f_prime(z);
error = abs(f(z)-f(3));
else
x1 = z;
z = x1 - (f1/((f1-f2)*(x1-x2)));
f3 = f_prime{z};
error = abs(f(z)-f(3));
end
end
plot (iteration, error, 'rx')
Risposte (1)
Walter Roberson
il 9 Ott 2021
f_prime = diff(f);
That line starts by looking to see if there is a variable named f that is in scope. If there is no such variable, then it looks to see if there is a function named f that is in scope. MATLAB sees the f.m file so Yes there is a function named f in scope. Having located the function named f, that syntax would attempt to invoke f without any arguments, just as if the code had written
f_prime = diff(f());
So the code in f.m starts running, with variable x (from the function definition line for function f) internally marked as missing. Then the second line of f is reached,
g = 2*((x-3)^2)+exp(0.5*x^2);
and the reference to x is seen. x is searched for as a variable in scope, and is located in the function header -- but since no parameters were passed, x is marked as missing. And MATLAB then complains that you invoked a function (namely f) with insufficient arguments.
Now... you need information beyond just the above.
What you need to know at this point is that MATLAB has two diff functions. (Well, more than two.)
The main diff function is designed to take numeric differences -- for a vector x and no optional arguments, it would output [x(2)-x(1), x(3)-x(2), x(4)-x(3), x(5)-x(4)] and so on to x(end)-x(end-1) . That kind of subtraction of adjacent elements is used for almost all data types. It is the "difference" operator, not the "differentiation" operator.
The second important diff function only applies to symbolic expressions and symbolic functions created by the Symbolic Toolbox, and in the context of symbolic expressions and symbolic functions, it is the differentiation operator.
But... your function f is a regular function, not a symbolic function. So you cannot invoke the differentiation operator on it -- not directly .
If you have access to the Symbolic Toolbox, what you could do would be to change
f_prime = diff(f);
into
syms x
f_prime = matlabFunction(diff(f(x)))
Creating x as symbolic, and passing it to x specifically results in function f being invoked with symbolic variable x as a parameter. The particular function you defined happens to be fine receiving a symbolic parameter, and would do a calculation that would return a symbolic expression. The symbolic expression would then get passed to the symbolic differentiation operator, returning a symbolic expression as a result. Then matlabFunction() would convert the symbolic expression into an anonymous function that can receive (and return) numeric values.
14 Commenti
Walter Roberson
il 9 Ott 2021
If you do not have access to the Symbolic Toolbox, then you will need to calculate the derivative of your f "by hand" and write that into a function... perhaps in a file named f_prime.m
Nizar Sharkas
il 10 Ott 2021
Walter Roberson
il 10 Ott 2021
In your "if" branch you use
f3 = f_prime(z);
In your "else" branch you use
f3 = f_prime{z};
Is there a reason for the difference?
Image Analyst
il 10 Ott 2021
@Walter Roberson I'd say that the reason is @Nizar Sharkas is unsure when to use braces, when to use parentheses, and when to use brackets. Perhaps the FAQ will explain part of that:
Nizar Sharkas
il 10 Ott 2021
Modificato: Walter Roberson
il 10 Ott 2021
Walter Roberson
il 10 Ott 2021
so if it took 100 iterations before the while loop condition was satisfied then we would have 100 different values of z).
You are not keeping track of the 100 different z values or 100 different f values, only of the current value. The current value is all you need for computation, but tracking the other values might be interesting for plotting or analysis.
Nizar Sharkas
il 10 Ott 2021
Walter Roberson
il 10 Ott 2021
syms x
f_prime = matlabFunction(diff(f(x)));
a = 0;
b = 3;
epsilon = 0.0001;
x1 = a;
x2 = b;
k = 0;
iteration = 100;
f1 = f_prime(x1);
f2 = f_prime(x2);
z(1) = x1 - (f1/((f1-f2)*(x1-x2)));
f3 = f_prime(z);
error = [];
while (abs(f3) > epsilon) && (k<iteration)
k = k+1;
if (f1>f2)
x2 = z(end);
z(end+1) = x1 - (f1/((f1-f2)*(x1-x2)));
f3 = f_prime(z(end));
error(end+1) = abs(f(z(end))-f(3));
else
x1 = z(end);
z(end+1) = x1 - (f1/((f1-f2)*(x1-x2)));
f3 = f_prime(z(end));
error(end+1) = abs(f(z(end))-f3);
end
end
plot(error, 'rx')
However... error here records the error "after" the iteration. Suppose that abs(f3)>epsilon was false right at the beginning so that the body of the while loop never executed, then what should be in error ?
With this code, z is always one element longer than error, because z(1) exists before the loop and each loop execution adds another value to z. But with your code, error does not exist until you have done a computation -- so when you just created z(3) then you would have just created error(2)
You could initialize error = inf instead of error = [] and then the lengths would match and error should in theory decrease as you go.
How do you want the graphs to appear in the case that the loop body does not execute?
Nizar Sharkas
il 10 Ott 2021
You were subtracting f(3) instead of f3
I renamed f3 to fpz (that is, fprime at z)
I suspect your error calculation is wrong
syms x
f(x) = 2*((x-3)^2)+exp(0.5*x^2);
f_prime = matlabFunction(diff(f(x)))
a = 0;
b = 3;
epsilon = 0.0001;
x1 = a;
x2 = b;
k = 0;
iteration = 100;
f1 = f_prime(x1);
f2 = f_prime(x2);
z(1) = x1 - (f1/((f1-f2)*(x1-x2)));
fpz(1) = f_prime(z);
error = [];
while (abs(fpz(end)) > epsilon) && (k<iteration)
k = k+1;
if (f1>f2)
x2 = z(end);
z(end+1) = x1 - (f1/((f1-f2)*(x1-x2)));
fpz(end+1) = f_prime(z(end));
error(end+1) = abs(f(z(end))-fpz(end));
else
x1 = z(end);
z(end+1) = x1 - (f1/((f1-f2)*(x1-x2)));
fpz(end+1) = f_prime(z(end));
error(end+1) = abs(f(z(end))-fpz(end));
end
end
plot(error, 'rx')
title('error vs iteration')
plot(1:length(z), f(z), 'g+', 1:length(fpz), fpz, 'bx')
title("f(z), f' vs iteration")
legend({'f(z)', "f'"})
[minfpz, idx] = min(abs(fpz))
double(f(z(idx)))
Walter Roberson
il 11 Ott 2021
Your current error function is looking for the place where f(z) == f'(z) . But that isn't necessarily where f(z) == 0 . f'(z) == 0 holds at critical points, not at zeros .
An example of a function where f(z) == f'(z) everywhere is f(z) = exp(z)
Nizar Sharkas
il 13 Ott 2021
That error is not occuring when I execute your code unchanged.
syms x
f(x) = 2*((x-3)^2)+exp(0.5*x^2);
f_prime = matlabFunction(diff(f(x)));
a = 0;
b = 3;
epsilon = 0.0001;
x1 = a;
x2 = b;
k = 0;
iteration = 100;
f1 = f_prime(x1);
f2 = f_prime(x2);
z(1) = x1 - (f1/((f1-f2)/(x1-x2)));
fpz(1) = f_prime(z);
error = [];
while (abs(fpz(end)) > epsilon) && (k<iteration)
k = k+1;
if (f1>f2)
x2 = z(end);
z(end+1) = x1 - (f1/((f1-f2)/(x1-x2)));
fpz(end+1) = f_prime(z(end));
error(end+1) = abs(f(z(end))-fpz(end));
sprintf('x_min=%f', z(end))
else
x1 = z(end);
z(end+1) = x1 - (f1/((f1-f2)/(x1-x2)));
fpz(end+1) = f_prime(z(end));
error(end+1) = abs(f(z(end))-fpz(end));
sprintf('x_min=%f', z(end))
end
end
plot(error, 'rx')
title('error vs iteration')
Walter Roberson
il 13 Ott 2021
Modificato: Walter Roberson
il 13 Ott 2021
my error is the absolute value of f(zi) - f(xopt) where zi is the values of z after each iteration and xopt is the value of z that finally breaks my while loop (optimum point).
In that case, do not calculate error inside the loop: keep track of all of the z values (which you are already doing), and after the loop,
fz = f(z);
error = fz - fz(end);
This of course only being valid if you converged within the allocated iterations: if you do not converge then fz(end) could be just about anything, and calculating the error relative to it would not be useful.
Categorie
Scopri di più su Linear Algebra in Centro assistenza e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!


