Erik M
Erik M

Reputation: 184

Matlab - dynamically produce string for anonymous function

I am trying to produce the argument string for an anonymous function based on the number of input arguments without using for loops. For example, if N=3, then I want a string that reads

@(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3))

I tried using repmat('ax',1,N) but I cannot figure out how to interleave the (i) index.

Any ideas?


Aside: Great answers so far, the above problem has been solved. To provide some intuition for those who are wondering why I want to do this: I need to construct a very large matrix anonymous function (a Jacobian) on the order of 3000x3000. I initially used the Matlab operations jacobian and matlabFunction to construct the anonymous function; however, this was quite slow. Instead, since the closed form of the derivative was quite simple, I decided to form the anonymous function directly. This was done by forming the symbolic Jacobian matrix, J, then appending it to the above @() string by using char(J{:})' and using eval to form the final anonymous function. This may not be the most elegant solution but I find it runs much faster than the jacobian/matlabFunction combination, especially for large N (additionally the structure of the new approach allows for the evaluation to be done in parallel).

EDIT: Just for completeness, the correct form of the argument string for the anonymous function should read

@(ax1,ax2,ax3,ay1,ay2,ay3)

to avoid a syntax error associated with indexing.

Upvotes: 2

Views: 264

Answers (3)

Luis Mendo
Luis Mendo

Reputation: 112659

Try this:

N = 3;
sx = strcat('ax(', arrayfun(@num2str, 1:N, 'uniformoutput', 0), '),');
sy = strcat('ay(', arrayfun(@num2str, 1:N, 'uniformoutput', 0), '),');
str = [sx{:} sy{:}];
str = ['@(' str(1:end-1) ')']

Upvotes: 1

Jonas
Jonas

Reputation: 74930

I suggest the following:

N = 3;
argumentString = [repmat('ax(%i),',1,N),repmat('ay(%i),',1,N)];

functionString = sprintf(['@(',argumentString(1:end-1),')'], 1:N, 1:N)

First, you create input masks for sprintf (e.g. 'ax(%i)'), which you then fill in with the appropriate numbers to create the function string.

Note: the syntax @(ax(1),...) will not actually work. More likely, you want to use either @()someFunction(ax(1),...), or you are trying to pass multiple input arguments to an existing function, in which case storing the inputs in a cell array and calling the function as fun(axCell{:}) would work.

Upvotes: 2

LowPolyCorgi
LowPolyCorgi

Reputation: 5171

A solution would be to use arrayfun:

sx = strjoin(arrayfun(@(x) ['ax(' num2str(x) ')'], 1:3, 'UniformOutput', false), ',');
sy = strjoin(arrayfun(@(x) ['ay(' num2str(x) ')'], 1:3, 'UniformOutput', false), ',');
s = ['@(' sx ',' sy ')'];

contains

'@(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3))'

Best,

Upvotes: 1

Related Questions