Why do I get Empty Plots during Optimization?
197 次查看(过去 30 天)
显示 更早的评论
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 个评论
dpb
2024-8-11,15:26
编辑:dpb
2024-8-11,15:28
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...
采纳的回答
Voss
2024-8-14,16:25
移动:Walter Roberson
2024-8-14,20:32
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)
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 个评论
更多回答(1 个)
dpb
2024-8-11,18:23
编辑:dpb
2024-8-12,15:08
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 个评论
Torsten
2024-8-14,15:33
Same for option 2:
options = optimoptions('ga', 'PlotFcn', @gaPlotRangeND);
[x, fval] = ga(@booth_func, 2, [], [], [], [], [], [], [], options);
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
2024-8-14,15:39
编辑:dpb
2024-8-14,16:02
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...
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Errorbars 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!