Why does the genetic algorithm in this case run only for one generation? and it's very slow.
Ältere Kommentare anzeigen
I'm using ga() for optimizing a 4-variable objective function. Below is my scrpit and attached file is the result.
ga runs only for one generation and it took 16412 seconds. In options I set MaxTime to be 5000 though. In this one generation, my objective function was called 150 times. How can I get more number of generations?
start_time = tic();
A = [];
b = [];
Aeq = [];
beq = [];
lb =[0.1; 0; 50; 0.1];
ub = [0.4; 0.9; 4000; 0.9];
to = [ 0.15, 0, 300, 0.3];
options = optimoptions('ga','display','iter', 'MaxTime', 5000);
[t,fval,exitflag,output] = ga(@objectivefun,4,A,b,Aeq,beq,lb,ub,@nonlco, options); % genetic algorithm
%[t,fval,exitflag,output] = particleswarm(@objectivefun, 4, lb, ub ); % Particle swarm optimization
%[t,fval,exitflag,output] = simulannealbnd(@objectivefun, t, lb,ub); %simulated annealing algorithm
toc(start_time);
function f = objectivefun(t)
load('G.mat');
load('Load');
p = t(1);
Trigger = t(2);
bgt = t(3);
alpha = t(4);
N = numnodes(G);
iter = 1;
tmax = 30;
M_iter = zeros(iter, tmax);
for jj = 1:iter
[G_dmg,~,~, needRemoveNode,LoadneedDist,M] = Load_initial(G,8,0,350,0.2,Load);
alreadyCalled = false; % Say that decision and implement have not been called yet.
for tt = 3: tmax
if any(needRemoveNode)|| ~any(needRemoveNode)
[G_dmg,LoadneedDist,needRemoveNode,M] = Load_Stages(G_dmg,needRemoveNode,LoadneedDist,M);
end
if (M(end) >= (Trigger * N)) && ~alreadyCalled % triggering level
% Calling for the very first time if we get here.
[G_dmg, Nodes_p] = Loads_decision(G_dmg);
[G_dmg] = Loads_implement(G_dmg, Nodes_p, p, bgt, alpha);
alreadyCalled = true; % Set flag to indicate we've called it.
elseif alreadyCalled
% Once they've been called already, call them regardless of the "if" test.
[G_dmg, Nodes_p] = Loads_decision(G_dmg);
[G_dmg, M] = Loads_implement(G_dmg, Nodes_p, M, p, bgt, alpha);
end
end
M_iter(jj,:)=M;
% S = std(M_iter);
% SE = S/sqrt(size(M_iter,1));
end
Mavg = mean(M_iter,1);
[~, maxidx] = max(Mavg);
f = find( (Mavg <= 0.05 * N) & (maxidx <= 1:length(Mavg)), 1 );
if isempty(f)
f = 31;
end
end
function [c, ceq] = nonlco (t)
c = [];
ceq = [];
end
15 Kommentare
Walter Roberson
am 3 Dez. 2021
load('G.mat');
load('Load');
Avoid using load() inside an optimization function. Load the variables before and pass the values in.
Walter Roberson
am 3 Dez. 2021
We have no idea how fast Loads_implement or Loads_decision or Load_Stages are, so we have no way of guessing what the slow operations are.
Question: is Loads_implement detecting how many output arguments are being used, and does less calculation if there is only one output argument?
Waseem AL Aqqad
am 3 Dez. 2021
Bearbeitet: Waseem AL Aqqad
am 3 Dez. 2021
Waseem AL Aqqad
am 3 Dez. 2021
Bearbeitet: Waseem AL Aqqad
am 3 Dez. 2021
Walter Roberson
am 3 Dez. 2021
Please look at this more closely:
if (M(end) >= (Trigger * N)) && ~alreadyCalled % triggering level
% Calling for the very first time if we get here.
[G_dmg, Nodes_p] = Loads_decision(G_dmg);
[G_dmg] = Loads_implement(G_dmg, Nodes_p, p, bgt, alpha);
alreadyCalled = true; % Set flag to indicate we've called it.
elseif alreadyCalled
% Once they've been called already, call them regardless of the "if" test.
[G_dmg, Nodes_p] = Loads_decision(G_dmg);
[G_dmg, M] = Loads_implement(G_dmg, Nodes_p, M, p, bgt, alpha);
end
In the two if cases, there is no difference in the calls to Loads_decision.
In the two if cases, the first difference in the calls to Loads_implement is that the first call does not return M, but the second call returns M. But if you look at the code for Loads_implement, the M that is passed in is passed out again unchanged in every case, so the effect is the same as if you do not assign to M in the call.
In the two if cases, the second difference in the calls to Loads_implement is that the first call does not pass in M, but ths second call passes in M. But let us look at the way that M is used in the function:
function [G_rec, M] = Loads_implement(G_dmg, Nodes_p, M, p, bgt, alpha,G_dmg_at_index_tt)
If you pass in M, then it matches the M in the calling sequence, and you get a normal looking situation where you are passing in 6 parameters and nargin is 6 and the names in the function definition line up nicely with the names passed in.
But now let us look at what happens if you do not pass in M. In that case, nargin is 5, and what is passed in as p is received into the M matrix, and what is passed in as bgt is received in the alpha matrix, and what is passed in as alpha is received into the bgt matrix. But then if you examine the code for nargin == 5, it is obviously using the bgt matrix as if it means the same thing as the bgt from the calling function, but because you did not pass in M, all the variables "fell down" one slot in matching to names, and the bgt variable inside the function holds the information you passed in as alpha .
If you want the Loads_implement to use a different algorithm for the two cases, then you need to find a way to still match up the variable names properly for the values you do pass in.
For instead of not passing in M at all (causing all the positions to fall down), pass in M as [] and use nargin and isempty(M) to detect which case you want to execute.
Waseem AL Aqqad
am 3 Dez. 2021
Walter Roberson
am 3 Dez. 2021
Okay, now another question:
Suppose that you have not set alreadyCalled and M(end)>= (Trigger*N) is false. Then the first part of the if is false and the second part is ~false == true, and false && true is false, so you move on to the elseif . Then in the elseif alreadyCalled is tested, and by hypothesis the variable is false so the elseif is false, so you will skip the elseif body, and will not have called any functions and will not have set any variables. So far so good, that sounds reasonable.
Now suppose you have not set alreadyCalled and M(end)>= (Trigger*N) is true. Then the first part of the if is true, and the second part is ~false == true, and true && true is true, so you execute the body of the if and call the functions and set alreadyCalled to true. Seems reasonable.
Now suppose that you have set alreadyCalled and M(end)>= (Trigger*N) is false. Then the first part of the if is false and the second part is ~true == false, and false && false is false, so you move on to the elseif. Then in the elseif alreadyCalled is tested, and by hypothesis the variable is true, so the elseif is true, so you will execute the functions (and not change alreadyCalled . Hmmm --- maybe this is okay ?? Let's keep looking
Now suppose you have set alreadyCalled and M(end)>=(Trigger*N) is true. Then the first part of the if is true and the second part is ~true == false, and true && false is false, so you move on to the elseif. Then in the elseif alreadyCalled is tested, and by hypothesis the variable is true, so the elseif is true, so you will execute the functions (and not change alreadyCalled . Hmmm -- maybe this is okay ??
But... do you really want to be calling the functions in the elseif branch no matter whether M(end)>=(Trigger*N) is true or false ?? If that is deliberate, the code could be written more clearly by making the if test only alreadyCalled and have it call the functions, and then have the elseif check M(end)>=(Trigger*N) only
Waseem AL Aqqad
am 3 Dez. 2021
Bearbeitet: Waseem AL Aqqad
am 3 Dez. 2021
Waseem AL Aqqad
am 3 Dez. 2021
Alan Weiss
am 3 Dez. 2021
ga(@objectivefun...
you most likely should have
ga(@(x)objectivefun(x,G,Load)...
where your objectivefun code should be
function y = objectivefun(x,G,Load)
Alan Weiss
MATLAB mathematical toolbox documentation
Waseem AL Aqqad
am 3 Dez. 2021
Waseem AL Aqqad
am 4 Dez. 2021
Walter Roberson
am 4 Dez. 2021
Please post your revised code. I still have concerns about your calculations.
Waseem AL Aqqad
am 4 Dez. 2021
Antworten (0)
Kategorien
Mehr zu Surrogate Optimization finden Sie in Hilfe-Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!