How to recursively reduce the function arguments

2 visualizaciones (últimos 30 días)
Victoria Li
Victoria Li el 9 de Nov. de 2021
Comentada: Victoria Li el 10 de Nov. de 2021
Is there a way to create a function with one less argument dynamically? Basicly I'd like to find a way to do the following recursively or in a loop.
f4 = @(x1,x2,x3,x4) f5(x1, x2, x3, x4, 1);
f3 = @(x1,x2,x3) f4(x1, x2, x3, 1);
...
f1 = @(x1) f2(x1, 1);
r = f1(1)
function r = f5(x1, x2, x3, x4, x5)
r = x1 + x2 + x3 + x4 + x5
end
  2 comentarios
David Hill
David Hill el 9 de Nov. de 2021
Very confusing. An example would be helpful. It seems to me that r=f1=f2=f3=f4=f5=4+x1; which equals 5 in the example above (x1=1). Not sure what you are trying to do, but it is not wise to have all those variables.
Victoria Li
Victoria Li el 9 de Nov. de 2021
Here is an example to calculate the double integral from 0 to 1 with composite simpson's rule. The function simpson2 takes a function argument. In the simpson2 function, I can only start the calculation when the function is a single variable. In the code below, I can transform the 2 variable function to a single variable function with given y values. I am looking for a more generic way to do this so it can handle integrals with more variables. To do this, it requires to transform the integral function with one less variable until it has only a single variable in each recursive iteration. The question above is simplified for achieving this.
f = @(x,y) (x.^2 + y.^2 );
a = 0;
b = 1;
m = 100;
integral = simpson2(a, b, m, f)
exact = integral2(f,a,b,a,b)
fprintf("Numerical Integral = %5.3f, Exact = %5.3f\n", integral, exact);
function integral = simpson2(a, b, m, fun)
% a, b: intregral boundary
% m: number of panels
% fun: function for integral
h = (b - a)/(2*m);
xi = a:h:b;
if nargin(fun) == 2
for i=1:length(xi)
fx = @(x) fun(x, xi(i)); % tranform to a single variable function with giver y varle
fx_val(i) = simpson2(a , b, m, fx);
end
elseif nargin(fun) == 1
fx_val = fun(xi);
fx_val(1);
else
fprintf("ERROR")
end
odd = double(sum(fx_val(3:2:end-1)));
even = double(sum(fx_val(2:2:end-1)));
integral = double(h/3 * (fx_val(1) + fx_val(end) + 4*(odd) + 2*(even)));
end

Iniciar sesión para comentar.

Respuesta aceptada

Stephen23
Stephen23 el 9 de Nov. de 2021
It can be done with VARARGIN:
N = 5;
C = cell(1,N);
C{N} = @f5;
for k = N-1:-1:1
C{k} = @(varargin) C{k+1}(varargin{:},1);
end
C{1}(1)
ans = 5
function r = f5(x1, x2, x3, x4, x5)
r = x1 + x2 + x3 + x4 + x5;
end
  1 comentario
Victoria Li
Victoria Li el 10 de Nov. de 2021
Thanks Stephen for the help. Your solution works perfectly.

Iniciar sesión para comentar.

Más respuestas (2)

Jan
Jan el 9 de Nov. de 2021
This should work with str2func and eval.
This is such a cruel programming technique, that I recommend not to use it. Such meta-programming for creating code dynamically is hard to debug and Matlab's JIT acceleration cannot work. This can slow down the code by a factor 100 compared to some code, which avoid the dynamic creation of variables and functions.
  1 comentario
Adam Danz
Adam Danz el 9 de Nov. de 2021
The function string could also be parsed to remove the penultimate input and then converted back to a function handle without using eval. But I still think there's a better approach.

Iniciar sesión para comentar.


Adam Danz
Adam Danz el 9 de Nov. de 2021
x1 = rand(1);
x2 = rand(1);
x3 = rand(1);
x4 = rand(1);
p = [x1, x2, x3, x4];
f5([p,1])
ans = 3.3148
p = [x1, x2, x3];
f5([p,1])
ans = 2.4283
p = [x1, x2];
f5([p,1])
ans = 1.8867
function f5(varargin)
sum([varargin{:}])
end

Categorías

Más información sobre Loops and Conditional Statements en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by