How to recursively reduce the function arguments

6 views (last 30 days)
Victoria Li
Victoria Li on 9 Nov 2021
Commented: Victoria Li on 10 Nov 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 Comments
Victoria Li
Victoria Li on 9 Nov 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

Sign in to comment.

Accepted Answer

Stephen
Stephen on 9 Nov 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 Comment
Victoria Li
Victoria Li on 10 Nov 2021
Thanks Stephen for the help. Your solution works perfectly.

Sign in to comment.

More Answers (2)

Jan
Jan on 9 Nov 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 Comment
Adam Danz
Adam Danz on 9 Nov 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.

Sign in to comment.


Adam Danz
Adam Danz on 9 Nov 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

Community Treasure Hunt

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

Start Hunting!