How to vectorise the code below

조회 수: 2 (최근 30일)
David Epstein
David Epstein 2018년 12월 21일
편집: Stephen23 2018년 12월 21일
I have asked about fsurf two or three times on this platform, and received two replies, neither of which extracted me from my difficulties. I have, however, made slow progress. I think I have found one bug in both execution and documentation of fsurf, and whether or not this is really a bug is still under consideration by Mathworks. I have finally succeeded in writing some code that actually outputs an image that seems to be related to what I am aiming at. The code is given the "green light" by the editor, but, when run produces many warnings. These all relate to the complaint that my code does not vectorize. Since the functions concerned are functions of two variables, I am not sure how fsurf would like me to change the code. Here is my code (called SE3):
close all; clear all; %#ok
R = 5; % centre of square is at r=R, z=0, where r is radial coord in (x,y)
%vertices of square in (x,z) plane.
A = [1,1,-1,-1,1;1,-1,-1,1,1];
figure; hold;
for x = 1:4
funx = @(ang,s) cos(ang)*(R + [cos(ang),sin(ang)]*(s*A(:,x)...
+ (1-s)*A(:,x+1)));
funy = @(ang,s) sin(ang)*(R + [cos(ang),sin(ang)]*(s*A(:,x)...
+ (1-s)*A(:,x+1)));
funz = @(ang,s)[-sin(ang),cos(ang)]*(s*A(:,x)+(1-s)*A(:,x+1));
fsurf(funx,funy,funz,[0,2*pi,0,1]);
end
hold off;
Here is the warning (only the first few lines of many warnings)
Warning: Function behaves unexpectedly on array inputs. To improve performance, properly vectorize
your function to return an output with the same size and shape as the input arguments.
> In matlab.graphics.function.ParameterizedFunctionSurface>checkVectorization
In matlab.graphics.function.ParameterizedFunctionSurface/set.XFunction
In matlab.graphics.function.ParameterizedFunctionSurface
In fsurf>singleFsurf (line 263)
In fsurf>@(f1,f2,f3)singleFsurf(cax,{f1,f2,f3},extraOpts,args) (line 236)
In fsurf>vectorizeFsurf (line 236)
In fsurf (line 200)
In SE3 (line 12)
  댓글 수: 8
David Epstein
David Epstein 2018년 12월 21일
@Stephen Cobeldick: Yes, I did ignore the instruction of have array inputs and outputs. I did this unconsciously, presumably because I couldn't make sense of the instruction. After this discussion, I do now understand what is required.
I had been ruling out the use of surf, because I was assuming it could only be used to display the graph of a real valued function of two variables. I looked again, after seeing your comment, and saw that one can use the syntax surf(X,Y,Z,C). This looks like a much better, and much simpler, approach than the one I was originally adopting, and on which you commented. And I can use matrices and matrix multiplication freely when defining X, Y and Z, which is a great relief.
@Rik Wisselink: Thanks for the further illumination. It's still a puzzle to me how I would use regular functions. (Anonymous functions are no good, because any natural code would require more than one executable.) In my code there are implicitly 12 distinct functions. A factor 4 for x=1:4 and a factor 3 for funx, funy and funz. As I understand Matlab (not very deeply) I cannot define regular functions in a loop. So this would be very ugly, very repetitive, and every improvement in the style of one function definition might be incorporated 12 times---which is very error prone.
I think I can now have a much more successful go at making this image. It has been a somewhat demoralizing experience trying and failing to get this to work, but I think that I finally know what I'm supposed to do.
Stephen23
Stephen23 2018년 12월 21일
편집: Stephen23 2018년 12월 21일
@David Epstein: personally I have never found a use for fsurf and fplot and all those other magical plotting functions. I like to know what my data is doing, which means using meshgrid or ndgrid and generating the values myself. Don't feel demoralized, just chalk it up to experience.
" It's still a puzzle to me how I would use regular functions.... In my code there are implicitly 12 distinct functions. A factor 4 for x=1:4 ..."
One way would be to note that x (and possibly others) are also variables: you don't just have a function of two variables, but a function of three (or four or five) variables, so you can write a function that with those input arguments:
function out = funX(ang,S,x,...)
out = ...
end
and then within the code you can specify those values explicitly or use define a parametrized function, e.g. within your loop:
fx = @(a,s)funX(a,s,x);
...
fsurf(fx, ...)
Thus it would be easy to bring it down to two functions by specifying the X/Y functions and inputting a function handle to distinguish:
function out = funXY(ang,S,x,fun)
out = fun(ang) .* ...;
end
So then you can specify the first factor when the function is parameterized:
fx = @(a,s)funXY(a,s,x,@cos);
fy = @(a,s)funXY(a,s,x,@sin);
...
fsurf(fx, fy, ...)

댓글을 달려면 로그인하십시오.

채택된 답변

Stephen23
Stephen23 2018년 12월 21일
Here are some vectorized versions of your functions:
R = 5;
A = [1,1,-1,-1,1;1,-1,-1,1,1];
B = cat(3,A(1,:),A(2,:));
for x = 1:4
% Vectorized:
fz = @(ang,s) sum(cat(3,-sin(ang),+cos(ang)).*(s.*B(1,x,:)+(1-s).*B(1,x+1,:)),3);
fa = @(ang,s) sum(cat(3,+cos(ang),+sin(ang)).*(s.*B(1,x,:)+(1-s).*B(1,x+1,:)),3);
fx = @(ang,s) cos(ang).*(R + fa(ang,s));
fy = @(ang,s) sin(ang).*(R + fa(ang,s));
% Original:
funx = @(ang,s) cos(ang)*(R + [cos(ang),sin(ang)]*(s*A(:,x) + (1-s)*A(:,x+1)));
funy = @(ang,s) sin(ang)*(R + [cos(ang),sin(ang)]*(s*A(:,x) + (1-s)*A(:,x+1)));
funz = @(ang,s)[-sin(ang),cos(ang)]*(s*A(:,x)+(1-s)*A(:,x+1));
% Compare:
new = fx(G,S); % can be called by FSURF.
old = arrayfun(funx,G,S);
all(abs(new(:)-old(:))<1e-10)
end

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 Surface and Mesh Plots에 대해 자세히 알아보기

제품


릴리스

R2018a

Community Treasure Hunt

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

Start Hunting!

Translated by