Invalid indexing or function definition. Indexing must follow MATLAB indexing. Function arguments must be symbolic variables, and function body must be sym expression.
30 Dec 2021
1 Answer
8 Views (30 days)
You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Show older comments
Hi all,
I am about to cut my veins because i have been for three days with this code and I can't fix the error. I have taken a look to the same error for other codes, but I can't see it in my code. Could someone tell me what is wrong? Below I paste the code. Thanks in advance!!
function c= regulafalsi (f, tol, ite, a, b)
% f= equation, tol=maximum error, ite = number of maximum iterations, a= right extreme of interval, b= left extreme of interval
syms x
syms f
syms a
syms b
syms c
f= @(x) exp(-x)-log(x);
f(a)= exp(-a)-log(a); %I have written these to see if I fixed the error, but not succeed
f(b)= exp(-b)-log(b);
f(c)= exp(-c)-log(c);
c = (a*f(b)-b*f(a))/(f(b)-f(a));
prod_ab=f(a) * f(b);
prod_ac=f(a) * f(c);
prod_bc=f(b) * f(c);
if prod_ab > 0
fprintf('El intervalo elegido no garantiza que contenga una solución.\n');
end
contador = 0;
while abs(b-a)>tol || contador<ite
if prod_ac<0
b = c;
elseif prod_bc<0
a = c;
elseif abs(f(c))<tol || contador<ite
fprintf('\La raíz es %f\n\n y el número de iteraciones es %f\n', c, contador)
contador = contador + 1;
end
%error messages received are:
%Error using sym/subsindex (line 953)
%Invalid indexing or function definition. Indexing must follow MATLAB indexing. Function arguments must be symbolic
%variables, and function body must be sym expression.
%Error in regulafalsi (line 9)
%f(a)= exp(-a)-log(a);
Accepted Answer
Voss
on 30 Dec 2021
f is a function (handle). If you want the value of f at a, you don't have to evaluate and store it like that. In fact, you cannot store something as f(a); this is the reason for the error. If you want to use the value of f at a, just say f(a) - no need to store it (but you can store it as some other variable, say, f_a = f(a), if you want to).
(Also, notice the Symbolic Math Toolbox is not used in the code below.)
f= @(x) exp(-x)-log(x);
a = 2;
b = 3;
c = (a*f(b)-b*f(a))/(f(b)-f(a));
prod_ab=f(a) * f(b);
prod_ac=f(a) * f(c);
prod_bc=f(b) * f(c);
disp(c)
0.8640
disp(prod_ab)
0.5850
disp(prod_ac)
-0.3167
disp(prod_bc)
-0.5954
8 Comments
Thank you very much for your quick answer!!
I have erased the f(a) and so on variables, and run the function but it seems that it enters in an infinite loop because the command window does not return any value. I have to press ctrl+c to stop the function, and then the following message appears:
>> f= @(x) exp(-x)-log(x);
>> f
f =
function_handle with value:
@(x)exp(-x)-log(x)
>> regulafalsi(f, 0.001, 6, 1, 1.5)
Operation terminated by user during regulafalsi (line 22)
In line 22, the code is: b = c;
The code as it is run is the following:
function c= regulafalsi (f, tol, ite, a, b)
syms x %definimos x como una variable simbólica
syms f %definimos f como una variable simbólica
f= @(x) exp(-x)-log(x);
c = (a*f(b)-b*f(a))/(f(b)-f(a));
prod_ab=f(a) * f(b);
prod_ac=f(a) * f(c);
prod_bc=f(b) * f(c);
%inputs: f es la función, tol es la tolerancia máxima, ite es el número de
%iteraciones máximas, y "a" es extremo derecho y "b" es el extremo izquierdo del primer intervalo.
% output es la aproximación a la raiz (c) y número de iteraciones necesarias para llegar a la raíz ("contador" final tras las veces realizadas en el bucle while).
if prod_ab > 0
%mandamos un mensaje de error porque no se ha elegido
%correctamente el intervalo ya que no se cumple el teorema de Bolzano
fprintf('El intervalo elegido no garantiza que contenga una solución.\n');
end
contador = 0; %creo un contador para el número de iteraciones que se van a realizar hasta encontrar la raíz
while abs(b-a)>tol || contador<ite
if prod_ac<0 %si es menor de cero, la raiz está en el intervalo
%[a-c] y se asigna c como el nuevo límite superior
b = c;
contador = contador + 1;
elseif prod_bc<0 %si es menor de cero, la raiz está en el intervalo
%[a-c] y se asigna c como el nuevo límite inferior
a = c;
contador = contador + 1;
elseif abs(f(c))<tol || contador<ite %finaliza al hallar la raiz comparando con la tolerancia introducida o el número máximo de iteraciones se ha alcanzado
fprintf('\La raíz es %f\n\n y el número de iteraciones es %f\n', c, contador)
end
end
In your code, where do you update prod_ab, prod_ac, prod_bc inside the while loop ?
f = @(x)exp(-x)-log(x)
f = function_handle with value:
@(x)exp(-x)-log(x)
regulafalsi(f, 0.001, 10, 1, 1.5)
contador = 0, error = 0.5
contador = 0, error = 0.5
b = 1.3343
contador = 1, error = 0.334306
b = 1.3343
contador = 2, error = 0.334306
b = 1.3343
contador = 3, error = 0.334306
b = 1.3343
contador = 4, error = 0.334306
b = 1.3343
contador = 5, error = 0.334306
b = 1.3343
contador = 6, error = 0.334306
b = 1.3343
contador = 7, error = 0.334306
b = 1.3343
contador = 8, error = 0.334306
b = 1.3343
contador = 9, error = 0.334306
b = 1.3343
ans = 1.3343
function c= regulafalsi (f, tol, ite, a, b)
syms x %definimos x como una variable simbólica
syms f %definimos f como una variable simbólica
f= @(x) exp(-x)-log(x);
c = (a*f(b)-b*f(a))/(f(b)-f(a));
prod_ab=f(a) * f(b);
prod_ac=f(a) * f(c);
prod_bc=f(b) * f(c);
%inputs: f es la función, tol es la tolerancia máxima, ite es el número de
%iteraciones máximas, y "a" es extremo derecho y "b" es el extremo izquierdo del primer intervalo.
% output es la aproximación a la raiz (c) y número de iteraciones necesarias para llegar a la raíz ("contador" final tras las veces realizadas en el bucle while).
if prod_ab > 0
%mandamos un mensaje de error porque no se ha elegido
%correctamente el intervalo ya que no se cumple el teorema de Bolzano
error('El intervalo elegido no garantiza que contenga una solución.\n');
end
contador = 0; %creo un contador para el número de iteraciones que se van a realizar hasta encontrar la raíz
fprintf('contador = %d, error = %g\n', contador, abs(b-a));
while abs(b-a)>tol && contador<ite
fprintf('contador = %d, error = %g\n', contador, abs(b-a));
if prod_ac<0 %si es menor de cero, la raiz está en el intervalo
%[a-c] y se asigna c como el nuevo límite superior
b = c
contador = contador + 1;
elseif prod_bc<0 %si es menor de cero, la raiz está en el intervalo
%[a-c] y se asigna c como el nuevo límite inferior
a = c
contador = contador + 1;
elseif abs(f(c))<tol || contador<ite %finaliza al hallar la raiz comparando con la tolerancia introducida o el número máximo de iteraciones se ha alcanzado
error('\La raíz es %f\n\n y el número de iteraciones es %f\n', c, contador)
else
contador = contador + 1;
fprintf('missing else was taken\n');
end
end
end
Hello Walter, Thank you for your answer! You're right, I forgot to put inside c formula into while loop. Now it works, but only if I enter into the code all values (a, b, tol, ite and f). I would like to do a general function in order to enter the inputs when calling the function, not having assigned into it. When I try this, it gives me an error in line 5:
'R_tilde = builtin('subsref',L_tilde,Idx);'
The working code with the inputs inside is as follows (thank to you):
function [c,contador] = regulafalsi (f, tol, ite, a, b)
syms x %definimos x como una variable simbólica
syms f %definimos f como una variable simbólica
f= @(x) exp(-x)-log(x);
tol=0.001;
ite=6;
a=1;
b=1.5;
c = (a*f(b)-b*f(a))/(f(b)-f(a));
prod_ab = f(a) * f(b);
prod_ac = f(a) * f(c);
prod_bc = f(b) * f(c);
%inputs: f es la función, tol es la tolerancia máxima, ite es el número de
%iteraciones máximas, y "a" es extremo derecho y "b" es el extremo izquierdo del primer intervalo.
% output es la aproximación a la raiz (c) y número de iteraciones necesarias para llegar a la raíz ("contador" final tras las veces realizadas en el bucle while).
if prod_ab > 0
%mandamos un mensaje de error porque no se ha elegido
%correctamente el intervalo ya que no se cumple el teorema de Bolzano
fprintf('El intervalo elegido no garantiza que contenga una solución.\n');
end
contador = 0; %creo un contador para el número de iteraciones que se van a realizar hasta encontrar la raíz
while abs(b-a)>tol && contador<ite
c = (a*f(b)-b*f(a))/(f(b)-f(a));
if prod_ac < 0 %si es menor de cero, la raiz está en el intervalo
%[a-c] y se asigna c como el nuevo límite superior
b = c;
contador = contador + 1;
elseif prod_bc<0 %si es menor de cero, la raiz está en el intervalo
%[a-c] y se asigna c como el nuevo límite inferior
a = c;
contador = contador + 1;
elseif f(c)==0 %si obtenemos directamente la raiz porque f(c) es cero
fprintf('La raíz es %f\n\n y el número de iteraciones es %f\n', c, contador)
end
end
fprintf('La raíz es %f\n\n y el número de iteraciones es %f\n', c, contador)
and the code I want to write without the assignments inside is as follows:
function [c,contador] = regulafalsi1 (f, tol, ite, a, b)
syms x %definimos x como una variable simbólica
syms f %definimos f como una variable simbólica
c = (a*f(b)-b*f(a))/(f(b)-f(a)); %calculamos el punto de corte inicial
prod_ab = f(a) * f(b);
prod_ac = f(a) * f(c);
prod_bc = f(b) * f(c);
%inputs: f es la función, tol es la tolerancia máxima, ite es el número de
%iteraciones máximas, y "a" es extremo derecho y "b" es el extremo izquierdo del primer intervalo.
% output es la aproximación a la raiz (c) y número de iteraciones necesarias para llegar a la raíz ("contador") final tras las veces realizadas en el bucle while).
if prod_ab > 0
%mandamos un mensaje de error porque no se ha elegido
%correctamente el intervalo ya que no se cumple el teorema de Bolzano
fprintf('El intervalo elegido no garantiza que contenga una solución.\n');
end
contador = 0; %creo un contador para el número de iteraciones que se van a realizar hasta encontrar la raíz
while (abs(b-a)>tol && contador<ite)
c = (a*f(b)-b*f(a))/(f(b)-f(a))
if prod_ac < 0 %si es menor de cero, la raiz está en el intervalo
%[a-c] y se asigna c como el nuevo límite superior
b = c
contador = contador + 1
elseif prod_bc<0 %si es menor de cero, la raiz está en el intervalo
%[a-c] y se asigna c como el nuevo límite inferior
a = c
contador = contador + 1
elseif (abs(f(c))>tol && contador<ite) %finaliza al hallar la raiz comparando con la tolerancia introducida o el número máximo de iteraciones se ha alcanzado
fprintf('\La raíz es %f\n\n y el número de iteraciones es %f\n', c, contador)
end
end
fprintf('La raíz es %f\n\n y el número de iteraciones es %f\n', c, contador)
Thank you very much for your tiem and your comments
When you use the second code, that does not hard-code the assignments, how are you invoking it?
I am very new in matlab and programming (just starting...) and I don't understand the question (sorry, this is my low level...)
When I type this in command window,
>> regulafalsi2(exp(-x)-log(x), 1, 1.5, 10, 0.00001)
It appears this message:
Index exceeds the number of array elements. Index must not exceed 1.
Error in sym/subsref (line 997)
R_tilde = builtin('subsref',L_tilde,Idx);
Error in regulafalsi2 (line 5)
fa=f(a); fb=f(b);
Notice the difference in how f was defined initially:
f= @(x) exp(-x)-log(x);
and how it is now:
exp(-x)-log(x)
You have to put the @(x) so that MATLAB knows it's a function, essentially. So you would call your function like this:
regulafalsi2(@(x) exp(-x)-log(x), 1, 1.5, 10, 0.00001)
But there is a second problem, which Walter mentioned at the start and which has not been corrected:
"In your code, where do you update prod_ab, prod_ac, prod_bc inside the while loop ?"
When you change the values of a and/or b you need to update all relevant variables that depend on those values, so not only c, which you have done, but also prod_ac and prod_bc, because if you don't update those, the code inside the while loop uses the old values which were based on the old a, b and c. (Also, notice that prod_ab is not used inside the while loop, but maybe it should be?)
Good morning Benjamin and Walter and happy 2022, thank you very much for the support in these days..
I have used the function feval() to calculate my f in each argument, also I have changed the code to update f(a), f(b) and f(c) into the while loop. I thought at first that, changing a, b and c was enough to change the associated function.
As it is a method that, in each loop selects a new interval, depending on which of the subintervals the product of the f(x) is < 0, it gets updated one or other, but substituting a or b by c. That is the reason why prod_ab does not change, because is the initial interval and is only evaluated once.
The updated (and at last) working code is:
function regulafalsi(f,a,b,nit,t)
%Inputs: f=función, a=valor inferior, b=valor superior, nit=número máximo
%de iteraciones, t=tolerancia
%Outputs: c=raíz, k=número de iteraciones realizadas
fa=feval(f,a); % utilizo la función feval para evaluar la función f en a
fb=feval(f,b);
disp('----------------------------------------------------------------------------------')
disp('iter a b c f(c) t ')
disp('----------------------------------------------------------------------------------')
fprintf('\n') %para que muestre cómo va realizando los bucles y el resultado en cada uno
if fa*fb>0 % si no cumple teorema de Bolzano
fprintf('No existe solución en el intervalo [%f,%f]',a,b);
c=[];
k=0;
l=0;
else
l=abs(b-a); %l es el tamaño del intervalo inicial
k=0; % k el número de iteraciones necesarias hasta que se cumpla la condición del while, iniciamos en cero
c = (a*fb-b*fa)/(fb-fa);% la fórmula de regula-falsi para calcular el punto de corte inicial
fc=feval(f,c); % utilizo la función feval para evaluar la función f en c
while t<=abs(f(c)) %mientras que el valor de la función en c en valor absoluto siga siendo mayor que la tolerancia (error que fijamos)
c = (a*fb-b*fa)/(fb-fa); %calculamos el punto de corte inicial; lo dejamos dentro del while para que e vaya actualizando en cada bucle
fc=feval(f,c); %calculamos cuánto vale c en la función que hemos introducido como f
if (fa*fc<0) %si el producto es menor de cero, la raiz está en el intervalo [a-c]
b=c; %se asigna c como el nuevo límite superior en vez de b
fb=fc; % se actualiza fb
k=k+1;%se añade una iteración al contador antes de comenzar el siguiente bucle
elseif (fb*fc<0) %si es menor de cero, la raiz está en el intervalo [c-b], y el resto como arriba pero sustituyendo c por a
a=c;
fa=fc;
k=k+1;
elseif fc==0 %si obtenemos directamente la raiz porque f(c) es cero
fprintf('\La raíz es %f\n\n', c)
end
Thank you again for all your help, I will remember these Xmas as "Regula-Falsi" ones...
Best regards,
Salceda
More Answers (0)
Categories
Find more on Language Fundamentals in Help Center and File Exchange
See Also
on 30 Dec 2021
on 1 Jan 2022
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)