Code covered by the BSD License

# Plot Multi Dimensional Functions

### Durga Lal Shrestha (view profile)

Evaluates multi dimensional functions; and visualizes and animates in two dimensions interactively.

plotfunction(fcn,LB,UB,varargin)
```function plotfunction(fcn,LB,UB,varargin)
%PLOTFUNCTION  plots any function in two dimensions
% This tool also animates the visualization interactively and is useful
% for optimization to see the minimum/maximum values of the function.
%
% USAGE:
%         PLOTFUNCTION(fcn,LB,UB)
%         PLOTFUNCTION(fcn,LB,UB,xypar)
%         PLOTFUNCTION(fcn,LB,UB,xypar,baseValue)
%         PLOTFUNCTION(fcn,LB,UB,xypar,baseValue,extra)
%
% INPUT:
%    fcn - handle to a function with scalar output
%    LB -  lower bound of the function parameter
%    UB -  upper bound of the function parameter
%    xypar - index of parameter vector to be plotted if dimension of the
%            paramter is greater than 2
%    baseValue - base value of the function parameters (except index
%                parameter)
%   extra - other additional parameter of the function
%
% OUTPUT:
%
% EXAMPLES:
% 1. plotfunction(@hosaki,[0 0],[5 5]);
%    Plot hosaki function in the range of 0 - 5 in both dimension.
%
% 2. LB = zeros(1,4);UB= 10*ones(1,4); xypar = [2 3];
%    plotfunction(@shekel,LB,UB,xypar);
%    Plot shekel function in the range of 0 - 10 in second and third
%    dimension while keeping constant value (average of 0 and 10) in
%    other dimensions.
%
% 3. baseValue = [3.2 4 4 6.8];
%    plotfunction(@shekel,LB,UB,xypar,baseValue);
%    Plot shekel function keeping constant value of 3.2 in first dimension and
%    6.8 in last dimension. Here values in second and thirs dimension is
%    overwriten by range of LB and UB as done in example 2.
%    %
% 4. For example you have the following function
%       f = parameterized_rosenbrock(x,a,b)
%       x1 = x(1);
%       x2 = x(2);
%       f = a * (x2 - x1^2)^b + (1 - x1)^b;
%
%    Use the following to visualise the above function
%    LB=[-5 -2];UB=[5 8];
%    a = 100; b = 2;   % additional argument to the function
%    plotfunction(@parameterized_rosenbrock,LB,UB,[],[],a,b)
%

% Author:Durga Lal Shrestha
% UNESCO-IHE Institute for Water Education, Delft, The Netherlands
% eMail: durgalal.shrestha@gmail.com
% Website: www.durgalal.co.cc
% Copyright 2004-2009 Durga Lal Shrestha.
% \$First created: 02-Feb-2010
% \$Revision: 1.0 \$ \$Date: 02-Feb-2010 15:33:06 \$

% ***********************************************************************
%% INPUT ARGUMENTS CHECK
if nargin <3
error('The number of input arguments should be at least 3');
end

if ~isa(fcn,'function_handle')
error('The first argument should be the function handle');
end

if length(LB) ~=length(UB)
error('Length of the lower bounds should be equal to length of the upper bounds');
end

% Index of parameter vector to be plotted in 3 dimension, where function
% value is z-dimension and x and y dimension is defined by xpar and ypar
% Default is 1 and 2.
xpar=1;
ypar=2;

if nargin>3 && ~isempty(varargin{1})
xypar = varargin{1};
if ~isvector(xypar) || length(xypar)~=2 || ~isequal(xypar,round(xypar))
error('Fourth argument should be integer vector of two elements');
end
xpar=xypar(1);
ypar=xypar(2);
if xpar > length(LB) || ypar > length(LB) || xpar < 1 || ypar < 1
error(['Elements of the fourth argument should not be greater than ' ...
'the dimension of the parameter vector and less than 1']);
end
end

%% default parameter values
baseValue = (UB + LB)/2;

if nargin>4 && ~isempty(varargin{2})
baseValue = varargin{2};
end

% Additional argument to the function
extra = {};
if nargin>5
extra = varargin(3:end);
end

npar = length(LB);
pts = 100;

%% Population of average values or user defined values
pop = ones(pts * pts,npar);
for i=1:npar
pop(:,i) = pop(:,i)*baseValue(i);
end

%% Varying the user defined parameter vector of the population
% Only two parameter vectors are changed, while keeping the average
% value for the rest of the parameter vector
span = (UB-LB)/(pts - 1);
x = LB(xpar): span(xpar) : UB(xpar);
y = LB(ypar): span(ypar) : UB(ypar);
k = 1;
for i = 1:pts
for j = 1:pts
pop(k,[xpar ypar]) = [x(i),y(j)];
k = k + 1;
end
end

%% Evaluating function at each row of pop
npop = length(pop);
values = zeros(npop,1);
for i=1:npop
values(i) = feval(fcn,pop(i,:),extra{:});
end

%% Plotting the surface of function
values = reshape(values,pts,pts);
h_surf = surf(x,y,values);

%% Interactive animation of function plot by rotating surface
h_push = uicontrol(gcf,'Style','pushbutton','String','Rotate',...
'Position',[10 10 100 40]);
set(h_push ,'Callback', {@rotateAgain,h_surf,h_push});
xlabel(['x' num2str(xpar)])
ylabel(['x' num2str(ypar)])
zlabel('function value')
title(['Function: ' func2str(fcn)])
axis tight

function  rotateAgain(varargin)
% ROTATEAGAIN rotate the surface plot along the z direction
% This sub function is called when the user click the "Rotate" button
% The user can also stop the rotation of the plot.
%
%%
h_surface=varargin{3};
h_pushButton = varargin{4};
str=get(h_pushButton,'String');
if strcmp(str,'Rotate Again')||strcmp(str,'Rotate')
set(h_pushButton,'String','Stop Rotation');
else
set(h_pushButton,'String','Rotate Again');
end
rotateAngle=1;     % Angle of rotation
rotatePause =0.05;
nRotate = 360/rotateAngle;
for i=1:nRotate
if strcmp(get(h_pushButton,'String'),'Rotate Again')
break;end
rotate(h_surface,[0 0 1],rotateAngle)
pause(rotatePause)
end
if i==nRotate
set(h_pushButton,'String','Rotate Again');
end
```