How to use global variable in nested function

44 views (last 30 days)
Atinesh Singh
Atinesh Singh on 15 Feb 2017
Edited: Jan on 16 Feb 2017
I need to use global variable in nested functions.
On running the below code, I'm getting an error
The GLOBAL or PERSISTENT declaration of "initial_flag" appears in a nested function, but should be in the outermost function where it is used.
Here is the logic of the below code:
There is a global variable named initial_flag which is defined in "demoEA.m" and "benchmark_func.m" and also in the nested function within "benchmark_func.m". The purpose of this variable is to avoid running code
if (func_num == 1) fhd = @f1;
elseif (func_num == 2) fhd = @f2;
end
multiple times in "benchmark_func.m" and avoid loading "datafiles/f01.mat" multiple times which contains the definition of (xopt, lb, ub) used in the nested functions.
Here is the Code.
"demoEA.m"
clear; clc; close all;
% Search Range
lb = -100;
ub = 100;
% Dimension
D = 1000;
NP = 100; % population size
runs = 2; % number of independent runs for each function, should be set to 25
Max_FEs = 1000; % maximal number of FEs, should be set to 3e+06
global initial_flag; % the global flag used in test suite
format short e;
for func_num = 1:2
for run = 1:runs
initial_flag = 0; % should set the flag to 0 for each run, each function
pop = lb + (ub-lb)*rand(D, NP); % Random Population
val = benchmark_func(pop, func_num); % fitness evaluation
FEs = NP;
while (FEs <= Max_FEs-NP)
% random search, you should add your own method
newpop = lb + (ub-lb)*rand(D, NP);
newval = benchmark_func(newpop, func_num); %returns a vector 1*100
FEs = FEs + NP;
index = (newval < val);
val(index) = newval(index);
pop(:, index) = newpop(:, index);
% demo output, you should save your results to some files
fprintf(1, 'func_num = %d, run = %d, FEs = %d\n', func_num, run, FEs);
fprintf(1, 'min(val) = %e\n\n', min(val));
end
end
end
"benchmark_func.m"
function fit = benchmark_func(x, func_num)
global initial_flag
persistent fhd
if (initial_flag == 0)
if (func_num == 1) fhd = @f1;
elseif (func_num == 2) fhd = @f2;
end
end
fit = fhd(x);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%BASE FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%------------------------------------------------------------------------------
% Elliptic Function
%------------------------------------------------------------------------------
function fit = elliptic(x)
[D ps] = size(x);
condition = 1e+6;
coefficients = condition .^ linspace(0, 1, D);
fit = coefficients * T_irreg(x).^2;
end
%------------------------------------------------------------------------------
% Rosenbrock's Function
%------------------------------------------------------------------------------
function fit = rosenbrock(x)
[D ps] = size(x);
fit = sum(100.*(x(1:D-1,:).^2-x(2:D, :)).^2+(x(1:D-1, :)-1).^2);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%BENCHMARK FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%------------------------------------------------------------------------------
% f1: Shifted Elliptic Function
% D = 1000
%------------------------------------------------------------------------------
function fit = f1(x)
global initial_flag
persistent xopt lb ub
[D ps] = size(x);
if (initial_flag == 0)
load 'datafiles/f01.mat';
initial_flag = 1;
end
idx = checkBounds(x, lb, ub);
x = x - repmat(xopt, 1, ps);
fit = elliptic(x);
fit(idx) = NaN;
end
%------------------------------------------------------------------------------
% f2: Shifted Rosenbrock’s Function
% D = 1000
%------------------------------------------------------------------------------
function fit = f2(x)
global initial_flag
persistent xopt lb ub
[D ps] = size(x);
if (initial_flag == 0)
load 'datafiles/f02.mat';
initial_flag = 1;
end
idx = checkBounds(x, lb, ub);
x = x - repmat(xopt, 1, ps);
fit = rosenbrock(x);
fit(idx) = NaN;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%HELPER FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%------------------------------------------------------------------------------
% This transformation is used to create smooth local irregularities.
%------------------------------------------------------------------------------
function g = T_irreg(f)
a = 0.1;
g = f;
idx = (f > 0);
g(idx) = log(f(idx))/a;
g(idx) = exp(g(idx) + 0.49*(sin(g(idx)) + sin(0.79*g(idx)))).^a;
idx = (f < 0);
g(idx) = log(-f(idx))/a;
g(idx) = -exp(g(idx) + 0.49*(sin(0.55*g(idx)) + sin(0.31*g(idx)))).^a;
end
%------------------------------------------------------------------------------
% This function tests a given decision vector against the boundaries of a function.
%------------------------------------------------------------------------------
function indices = checkBounds(x, lb, ub)
indices = find(sum(x > ub | x < lb) > 0);
end
end
Please help me to solve this issue. For complete code please refer attachments.
  3 Comments
Rik
Rik on 16 Feb 2017
Still, the answer stands that variables are by definition shared between the main function and the nested function. Remove the global and you should be fine. You could also just load the data in the main function, because now you will have to reload the data. the .mat is loaded in a nested function, so after the call, all variables that were not shared by the main function are removed.
Passing of variables is a way better solution in almost any imaginable case. You can also take a look at varargin, varargout, nargin and nargout.

Sign in to comment.

Accepted Answer

Jan
Jan on 16 Feb 2017
Edited: Jan on 16 Feb 2017
As mentioned in the comments already:
Using globals leads to the same problems every time: The distribution is buggy and it is hard to control, which part of the code is responsible for the last change of the value. Therefore globals impede the programming and the debugging. This does not matter Matlab only, but all programming languages. Therefore it is a good programming practice, to avoid globals, or in your case to modify the code to work without them.

More Answers (0)

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by