Vectorizing a function handle with some constant inputs

9 visualizaciones (últimos 30 días)
Mohammad Shojaei Arani
Mohammad Shojaei Arani el 18 de En. de 2022
Respondida: Shivang el 23 de Oct. de 2023
Hello friends!
I have an annoying problem and need your kind help!
Suppose that I have a symbolic vector like f = [x+y;0;x.*y;2.*x;0] where both x and y are vectors of the same size. As you see, some of the elements of f are 0. Imagine that we do not know, beforehand, which one is zero. Now, I want to ake a function handle out of it which is simple as bellow
g = matlabFunction(f);g
g =
function_handle with value:
@(x,y)[x+y;0.0;x.*y;x.*2.0;0.0]
Now, if I want to rund the command g([1 2],[3 4]) then clearly I get erros (dimension mismatch). Here, I have 2 problems. First, I do not know, beforehand, which element is 0 to fix the problem. Second, even if I know which is 0 it would not be easy to fix it through 'matlabFunction' (though it is possible through @() operation). I explain more. One way to fix the problem (assuming I know that second and last components are 0) is as bellow:
g = @(x,y)[x+y;0*x;x.*y;x.*2.0;0.*x];
but, if I only have access to the symbolic expression f = [x+y;0;x.*y;2.*x;0] and if I write f = [x+y;0.*x;x.*y;2.*x;0.*x] then the command g = matlabFunction(f) first simplifies f and then I am in trouble again. I did find a nice solution as bellow:
>> tmp = arrayfun(g, [1 2],[3 4], 'uni', 0);
tmp = cat(2, tmp{:})
tmp =
4 6
0 0
3 8
2 4
0 0
but this has the problem that increases the computational time, unfortunately. Please note that my actual problem is not this simple and my f function is a super big multi-component function (and x and y have rather big dimensions like 1-by-1000 not 1-by-2) which must be calculated in a for-loop thousands of time. So, I need a solution which fixes the root of the problem, that is a solution which corrects g by notifying the zero components and replaces them by 0.*x. To give you a feeling about how the computational time between the 2 approaches differ run the following
syms x y
f = [x+y;0;x.*y;2.*x;0];
g = matlabFunction(f);
g1= @(x,y)[x+y;0.*x;x.*y;2.*x;0.*x];
N=100000;
x=[1 2];y=[3 4];
tic;
for n=1:N
g1(x,y);
end
h1=toc;
tic;
for n=1:N
tmp = arrayfun(g, 1:5,1:5, 'uni', 0);
tmp = cat(2, tmp{:});
end
h2=toc;
[h1/N h2/N]
ans =
9.8002e-07 1.6842e-05
Any idea for this extremely annoying problem? If there is no good answer to my question then I hope that in the next version of matlab they fix this (they can easily fix it but perhaps they did not predict this).
Thank you in advance!
Babak

Respuestas (1)

Shivang
Shivang el 23 de Oct. de 2023
Hi Mohammad,
Based on my understanding, your issue is that "matlabFunction" simplies the symbolic expression fed to it, which can cause dimension mismatch errors during evaluation.
The following workaround should help resolve your problem. After obtaining a function handle from the "matlabFunction" command, you can convert it to a string using the "func2str" function. You can then use the "strrep" function to replace all '0's with '0.*x'. Apply the "str2func" function to this modified string to go back to a function handle. You should not see any dimension mismatch errors while evaluating the function now.
See the sample code below.
syms x y
f = [x+y;0;x.*y;2.*x;0];
g = matlabFunction(f)
g = function_handle with value:
@(x,y)[x+y;0.0;x.*y;x.*2.0;0.0]
str = func2str(g);
str_new = strrep(str, '0.0', '0.*x');
g_new = str2func(str_new)
g_new = function_handle with value:
@(x,y)[x+y;0.*x;x.*y;x.*2.0;0.*x]
g_new([1 2],[3 4])
ans = 5×2
4 6 0 0 3 8 2 4 0 0
Hope this helps.
Regards,
Shivang

Community Treasure Hunt

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

Start Hunting!

Translated by