# Why do I get Empty Plots during Optimization?

6 visualizaciones (últimos 30 días)
B. Burak el 10 de Ag. de 2024
Comentada: Torsten el 14 de Ag. de 2024
Inspired by custom plotting given here, for one-dimensional design variable case, I would like to generalize it to n-dimensional case. I wrote the following code to achieve that:
function state = gaPlotRangeND(options, state, flag)
% gaPlotRangeND Plots the mean and the range of the population for n-dimensions.
% STATE = gaPlotRangeND(OPTIONS, STATE, FLAG) plots the mean and the range
% (highest and the lowest) of individuals for each variable.
generation = state.Generation;
population = state.Population;
numVars = size(population, 2);
M = mean(population);
L = M - min(population);
U = max(population) - M;
switch flag
case 'init'
for i = 1:numVars
subplot(numVars, 1, i);
set(gca, 'xlim', [1, options.MaxGenerations + 1]);
plotRange = errorbar(generation, M(:, i), L(:, i), U(:, i));
set(plotRange, 'Tag', ['Var_' num2str(i)]);
title(['Range of Population, Mean for Variable ' num2str(i)], 'interp', 'none')
xlabel('Generation', 'interp', 'none')
end
case 'iter'
for i = 1:numVars
subplot(numVars, 1, i);
plotRange = findobj(get(gca, 'Children'), 'Tag', ['Var_' num2str(i)]);
newX = [get(plotRange, 'Xdata'), generation];
newY = [get(plotRange, 'Ydata'), M(:, i)];
newL = [get(plotRange, 'Ldata'), L(:, i)];
newU = [get(plotRange, 'Udata'), U(:, i)];
set(plotRange, 'Xdata', newX, 'Ydata', newY, 'Ldata', newL, 'Udata', newU);
end
end
end
When I run it for a simple two-dimensional test problem defined below, it does not work. It just outputs two empty subplots on top of each other during execution of genetic algorithm, and ends with a single empty plot. It is supposed to plot mean and range of population at each iteration for each variable, which is two in this case.
function y = booth_func(x)
y = (x(1) + 2 * x(2) - 7) ^ 2 + (2 * x(1) + x(2) - 5) ^ 2;
end
options = optimoptions('ga', 'PlotFcn', @gaPlotRangeND);
[x, fval] = ga(@booth_func, 2, [], [], [], [], [], [], [], options);
How can I solve this issue? What do I miss here?
##### 3 comentariosMostrar 1 comentario más antiguoOcultar 1 comentario más antiguo
B. Burak el 11 de Ag. de 2024
I added breakpoints to observe as you suggested, but under 'iter' plotRange returns 0x0 empty GraphicsPlaceholder array.
dpb el 11 de Ag. de 2024
Editada: dpb el 11 de Ag. de 2024
This is probably going to be complicated, but...in
case 'init'
for i = 1:numVars
subplot(numVars, 1, i);
set(gca, 'xlim', [1, options.MaxGenerations + 1]);
...
You are creating multiple subplot axes and you have not saved the handle to any of them to later be able to address which of them you want...and, using gca simply will return whatever happens to be the current axes at the time it is called which will always be the last one referenced (which might be any one if user clicks on one during code execution).
At a barest minimum you'll need an array of axes handles to the various suplot axes objects and have to address each one in turn inside the iteration case code.
Not having the toolbox, no way can try anything specific here, but there's at least a starting point to try to work out the issues...
I'd suggest it also may be a place to use the tiledlayout instead of subplot()

Iniciar sesión para comentar.

Voss el 14 de Ag. de 2024
Movida: Walter Roberson el 14 de Ag. de 2024
Specifying the OutputFcn rather than the PlotFcn seems to provide something like what was intended.
options = optimoptions('ga', 'OutputFcn', @gaPlotRangeND);
[x, fval] = ga(@booth_func, 2, [], [], [], [], [], [], [], options)
ga stopped because it exceeded options.MaxGenerations.
x = 1x2
1.0052 3.0107
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
fval = 0.0012
function y = booth_func(x)
y = (x(1) + 2 * x(2) - 7) ^ 2 + (2 * x(1) + x(2) - 5) ^ 2;
end
function [state,options,optchanged] = gaPlotRangeND(options, state, flag)
% gaPlotRangeND Plots the mean and the range of the population for n-dimensions.
% [STATE,OPTIONS,OPTCHANGED] = gaPlotRangeND(OPTIONS, STATE, FLAG) plots the
% mean and the range (highest and the lowest) of individuals for each variable.
generation = state.Generation;
population = state.Population;
numVars = size(population, 2);
M = mean(population);
L = M - min(population);
U = max(population) - M;
persistent hAx hEB
switch flag
case 'init'
f = figure();
hAx=gobjects(size(M)); % prealloate for axes handles
hEB=gobjects(size(M)); % and for errorbars, too...
for i = 1:numVars
hAx(i)=subplot(numVars, 1, i, 'Parent', f); % create subplot, save handle to each
hEB(i)=errorbar(generation, M(:, i), L(:, i), U(:, i)); % save handle to ith EB
xlim(hAx(i),[1 options.MaxGenerations+1]);
title(hAx(i),['Range of Population, Mean for Variable ' num2str(i)])
xlabel(hAx(i),'Generation')
end
case 'iter'
for i = 1:numVars
newX=[hEB(i).XData, generation]; % return existing data
newY=[hEB(i).XData, M(:, i)];
newL=[hEB(i).YNegativeDelta,L(:, i)]; % must use correct field names...
newU=[hEB(i).YPositiveDelta,U(:, i)];
set(hEB(i),'Xdata',newX,'Ydata',newY,'YNegativeDelta',newL,'YPositiveDelta',newU);
end
end
optchanged = false;
end
##### 3 comentariosMostrar 1 comentario más antiguoOcultar 1 comentario más antiguo
B. Burak el 14 de Ag. de 2024
Movida: Walter Roberson el 14 de Ag. de 2024
@Voss -- This is amazing! I think your original reply deserves to be accepted as solution to my query. If you separately post it as an answer to this thread, I would be glad to accept it as answer.
Torsten el 14 de Ag. de 2024
Strange behaviour of "ga" for the problem at hand ...

Iniciar sesión para comentar.

### Más respuestas (1)

dpb el 11 de Ag. de 2024
Editada: dpb el 12 de Ag. de 2024
Per the above comments, at least a start would be something more like...
function state = gaPlotRangeND(options, state, flag)
% gaPlotRangeND Plots the mean and the range of the population for n-dimensions.
% STATE = gaPlotRangeND(OPTIONS, STATE, FLAG) plots the mean and the range
% (highest and the lowest) of individuals for each variable.
generation = state.Generation;
population = state.Population;
numVars = size(population, 2);
M = mean(population);
L = M - min(population);
U = max(population) - M;
switch flag
case 'init'
hAx=gobjects(size(M)); % prealloate for axes handles
hEB=gobjects(size(M)); % and for errorbars, too...
for i = 1:numVars
hAx(i)=subplot(numVars, 1, i); % create subplot, save handle to each
set(hAx(i), 'xlim', [1, options.MaxGenerations+1]);
hEB(i)=errorbar(generation, M(:, i), L(:, i), U(:, i)); % save handle to ith EB
title(hAx(i),['Range of Population, Mean for Variable ' num2str(i)])
xlabel(hAx(i),'Generation')
end
case 'iter'
for i = 1:numVars
newX=[hEB(i).XData, generation]; % return existing data
newY=[hEB(i).XData, M(:, i)];
newL=[hEB(i).YNegativeData,L(:, i)]; % must use correct field names...
newU=[hEB(i).YPositiveData,U(:, i)];
set(hEB(i),'Xdata',newX,'Ydata',newY,'YNegativeData',newL,'YPositiveData',newU);
end
end
end
Should at least have a chance...
##### 34 comentariosMostrar 32 comentarios más antiguosOcultar 32 comentarios más antiguos
Torsten el 14 de Ag. de 2024
Same for option 2:
options = optimoptions('ga', 'PlotFcn', @gaPlotRangeND);
[x, fval] = ga(@booth_func, 2, [], [], [], [], [], [], [], options);
Unrecognized method, property, or field 'XData' for class 'matlab.graphics.GraphicsPlaceholder'.

Error in solution>gaPlotRangeND (line 34)
newX=[hEBi.XData, generation]; % return existing data

optimValues = plotfcn(varargin{1:end});

[state,optimValues] = callOnePlotFcn(fname,plotNames{i},state,options.OutputPlotFcnOptions,optimValues,flag,args{i}{:});

Error in gaunc (line 116)

Error in ga (line 417)
[x,fval,exitFlag,output,population,scores] = gaunc(FitnessFcn,nvars, ...
function y = booth_func(x)
y = (x(1) + 2 * x(2) - 7) ^ 2 + (2 * x(1) + x(2) - 5) ^ 2;
end
function state = gaPlotRangeND(options, state, flag)
% gaPlotRangeND Plots the mean and the range of the population for n-dimensions.
% STATE = gaPlotRangeND(OPTIONS, STATE, FLAG) plots the mean and the range
% (highest and the lowest) of individuals for each variable.
generation = state.Generation;
population = state.Population;
numVars = size(population, 2);
M = mean(population);
L = M - min(population);
U = max(population) - M;
switch flag
case 'init'
hAx=gobjects(size(M)); % prealloate for axes handles
hEB=gobjects(size(M)); % and for errorbars, too...
for i = 1:numVars
hAx(i)=subplot(numVars, 1, i); % create subplot, save handle to each
hold(hAx(i),'on') % hold on to add more later
xlim(hAx(i),[1 options.MaxGenerations+1])
hEB(i)=errorbar(generation, M(:, i), L(:, i), U(:, i)); % save handle to ith EB
title(hAx(i),['Range of Population, Mean for Variable ' num2str(i)])
xlabel(hAx(i),'Generation')
end
case 'iter'
for i = 1:numVars
hAxi=subplot(numVars,1,i); % the axes handle
hEBi=findobj(hAxi,'Type','ErrorBar'); % find the EB object
newX=[hEBi.XData, generation]; % return existing data
newY=[hEBi.XData, M(:, i)];
newL=[hEBi.YNegativeData,L(:, i)]; % must use correct field names...
newU=[hEBi.YPositiveData,U(:, i)];
set(hEBi,'Xdata',newX,'Ydata',newY,'YNegativeData',newL,'YPositiveData',newU);
end
end
end
dpb el 14 de Ag. de 2024
Editada: dpb el 14 de Ag. de 2024
That's truly bizarre! ga has to be mucking around with the HG environment behind the scenes...
I don't suppose you put a breakpoint into the 'iter' case to see what gca returns as compared to the saved hAx, did you? It's truly mind-boggling that those are really no longer valid handles to the initially-created axes...

Iniciar sesión para comentar.

### Categorías

Más información sobre Errorbars en Help Center y File Exchange.

R2024a

### Community Treasure Hunt

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

Start Hunting!

Translated by