How to differentiate between an index and a value in a function?

조회 수: 1(최근 30일)
Michael Ryan
Michael Ryan 2021년 10월 27일
댓글: Bjorn Gustavsson 2021년 10월 27일
The summary isn't great, so hopefully my explanation will make more sense.
I have four inputs to a function.
f = @(x)[0.5*(cos(x(1)))-0.5*(sin(x(2)))-(x(1));0.5*(sin(x(1)))+0.5*(cos(x(2)))-(x(2))]
J = @(x)[-0.5*sin(x(1))-1,-0.5*cos(x(2));0.5*cos(x(1)),-0.5*sin(x(2))-1]
x_0 = [0 0]
E_tol = 10^-4
x_0 is the initial value of x, for which I plan to calculate x1, x2,....xn-1, xn. However, when I type in J(x_0) in my script, MATLAB sees the x_0 as an index, rather than values to be plugged into the function, J. In the Command Window it works perfectly.
How do I distiguish between an index and a value when using function handles?
This is the rest of my unfinished code incase it's relevant.
function x = my_newton_raphson(f,J,x_0,E_tol)
clc
%Setting Matrices and Constants
n = 0;
E = 0;
x = zeros(1,length(f));
J_0 = J(x_0(1),x_0(2));
invJ = inv(J);
%Inital Values
x(1) = x_0 - invJ(x_0(1),x_0(2)) * f(x_0(1),x_0(2));
deltaX = x(1) - x_0;
deltaE = sqrt((deltaX(1)^2) + (deltaX(2)^2));
E = E + deltaE;
n = n + 1;
%Newton-Raphson Iteration
if J_0 == 0
fprintf('no suitable starting vector')
else
while E < E_tol
f(n) = f(x(n));
x(n+1) = x(n) - invJ(n) * f(n);
deltaX = x(k+1) - x(k);
deltaE = sqrt((deltaX(1)^2) + (deltaX(2)^2));
E = E + deltaE;
n = n + 1;
end
end
fprintf('x = ')
disp(x)
fprintf('n = ')
disp(n)
end
And this is the error:
Index in position 1 is invalid. Array indices must be positive integers or logical values.
Error in my_newton_raphson (line 11)
J_0 = J(x_0(1),x_0(2));
Thanks.

답변(2개)

Bjorn Gustavsson
Bjorn Gustavsson 2021년 10월 27일
Your function J expects a single input as defined. I get:
J_0 = J(x_0);
to run without problems...
HTH
  댓글 수: 2
Bjorn Gustavsson
Bjorn Gustavsson 2021년 10월 27일
OK, here we go.
You have several bugs in your code, since it is not exactly clear what you want to do I can not give you a complete list of corrections, but point out a couple of points I find dubious and think you want something else. Then I'll advice you to debug your code step-by-step.
This seems to be a multidimensional Newton-Raphson-equation solver. For such a you want inputs of the function f with one vector for the variables, not a list of the different components of the input-vector. Then you want the Jacobian, or rather the inverse of the jacobian, again as a function of the vector of unknowns. You have defined those where you define your f and J. Then in the function you call them with the components of x as 2 scalar input arguments. Then you also confuse how you can use the function-handles and arrays for function-values/output-values during the iteration. A couple of corrections you most likely want:
J_0 = J(x_0(1),x_0(2)); % in your my_newton_raphson
invJ = inv(J);
% should most likely be:
J_0 = J(x_0); % Jacobian at initial point.
invJ = @(x) inv(J(x)); % Function-handle of the inverse of the Jacobian at N-D point x (here N is 2)
Then:
%Inital Values
x(1) = x_0 - invJ(x_0(1),x_0(2)) * f(x_0(1),x_0(2));
deltaX = x(1) - x_0;
deltaE = sqrt((deltaX(1)^2) + (deltaX(2)^2));
E = E + deltaE;
% should probably be:
%Inital Values
x = x_0 - invJ(x_0) * f(x_0); % Note the change x is an array with your unknown x1 and x2
deltaX = x - x_0; % Step away from starting position, seems strange?
deltaE = sqrt((deltaX(1)^2) + (deltaX(2)^2)); % length away from starting position
E = E + deltaE; % This seems very odd, sum of the length of x away from initial position, why?
Further you have:
f(n) = f(x(n));
x(n+1) = x(n) - invJ(n) * f(n);
Here you try to assign the output from the function in function-handle f (2-by-1 array) to an element n of f. Then you try to evaluate f with a scalar integer input, when it expects a 2-D array as input. These lines should be something like:
fvals(:,n) = f(x(:,n));
x(:,n+1) = x(:,n) - invJ(x(:,n)) * f(x(:,n));
There are very likely more bugs in your function. To verify that your function does what you want step through it in debug-mode. That is set:
dbstop in my_newton_raphson
Befor you try to run the function. Then you can execute the function line-by-line, either by typing dbstep at the command-line of pushing the "step" button in the editor. Between each step you can then inspect the values of each variable and check that the next line doesn't error. This is the way to stepwise convert a quickly written sketch of an algorithm into working code.
HTH

댓글을 달려면 로그인하십시오.


Steven Lord
Steven Lord 2021년 10월 27일
Please show us exactly how you call my_newton_raphson and how you construct the input arguments you pass into my_newton_raphson. You expect the second input to be a function handle (as in the first example below with the first input to the integral function) but I suspect instead you're doing something like evaluating that function handle to generate a vector and passing that vector in as the second input (as in the second example below.) If integral didn't check its first input was a function handle explicitly, that second example likely would have thrown the error message you received.
integral(@sin, 0, pi) % passes a function handle as the first input, works
ans = 2.0000
integral(sin(0:0.1:pi), 0, pi) % passes a vector as the first input, errors
Error using integral (line 81)
First input argument must be a function handle.

제품


릴리스

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by