Why do I get Empty Plots during Optimization?
Mostra commenti meno recenti
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 Commenti
Mario Malic
il 10 Ago 2024
I would suggest to set breakpoints in your lines where you change plot or change plot properties. While there, inspect if plotRange is found.
B. Burak
il 11 Ago 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...
Risposta accettata
Più risposte (1)
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 Commenti
"Variable might be used before it is defined" for hEB(i)..."
Did the initialization case execute and did you use hEB for the handles array for the error bar? The subsequent error makes it look like maybe not...but would have to see the code as you actually ran it to tell any more.
There's no variable "errBars" in my code; you'll have to fixup whatever you changed to be the handle variables if don't keep the same naming convention I used...
Without the actual code as you ran it, can't really say much else...I used hEB for the errorbar handles as the mnemonic naming convention...
B. Burak
il 11 Ago 2024
dpb
il 11 Ago 2024
Again, we need to see the code AS YOU RAN IT.
Did you set a breakpoint an ensure the initialization code is being executed?
If so, since this is a callback function, the issue is likely that the local variables are not retained between invocations; they're defined in the intialization call, but then go out of scope and aren't available later when the other calls are made.
That's complicating difference between what you're trying to do and the simpler case of the example where there's only one axis so gca refers to the right one...
Make the hEB and hAX arrays global or persistent so they are available; or do like a AppDesigner application and create a global app structure and put them in it...
Mario Malic
il 11 Ago 2024
Make them persistent, that should be enough.
Walter Roberson
il 11 Ago 2024
I agree, make them persistent.
Walter Roberson
il 11 Ago 2024
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;
persistent hAx hEb
switch flag
case 'init'
delete(hEB); %get rid of lingering objects
delete(hAx); %get rid of lingering objects
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
dpb
il 12 Ago 2024
Alternatively, without the need for persistent on the original lines @B. Burak was trying to follow...
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;
persistent hAx hEb
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
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
Will be just a little less efficient in having to find the error bar object handle every time through...
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;
persistent hAx hEb
switch flag
case 'init'
delete(hEB); %get rid of lingering objects
delete(hAx); %get rid of lingering objects
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
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;
persistent hAx hEb
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
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
The MATLAB example works for one variable:
options = optimoptions('ga','PlotFcn',@gaplot1drange);
[x,fval] = ga(@two_min,1,[],[],[],[],[],[],[],options)
function y = two_min(x)
if x <= 100
y = -exp(-(x/100)^2);
else
y = -exp(-1) + (x-100)*(x-102);
end
end
function state = gaplot1drange(options,state,flag)
%gaplot1drange Plots the mean and the range of the population.
% STATE = gaplot1drange(OPTIONS,STATE,FLAG) plots the mean and the range
% (highest and the lowest) of individuals (1-D only).
%
% Example:
% Create options that use gaplot1drange
% as the plot function
% options = optimoptions('ga','PlotFcn',@gaplot1drange);
% Copyright 2012-2014 The MathWorks, Inc.
if isinf(options.MaxGenerations) || size(state.Population,2) > 1
title('Plot Not Available','interp','none');
return;
end
generation = state.Generation;
score = state.Population;
smean = mean(score);
Y = smean;
L = smean - min(score);
U = max(score) - smean;
switch flag
case 'init'
set(gca,'xlim',[1,options.MaxGenerations+1]);
plotRange = errorbar(generation,Y,L,U);
set(plotRange,'Tag','gaplot1drange');
title('Range of Population, Mean','interp','none')
xlabel('Generation','interp','none')
case 'iter'
plotRange = findobj(get(gca,'Children'),'Tag','gaplot1drange');
newX = [get(plotRange,'Xdata') generation];
newY = [get(plotRange,'Ydata') Y];
newL = [get(plotRange,'Ldata') L];
newU = [get(plotRange,'Udata') U];
set(plotRange,'Xdata',newX,'Ydata',newY,'Ldata',newL,'Udata',newU);
end
end
B. Burak
il 12 Ago 2024
Are you sure the initialization code ran? Set breakpoints...looks as though should work if so.
You need to determine precisely which variable/object and which pass through the loop it is that is throwing the error...is it actually the graphics handle or the other variables on the callback?
I keep forgetting the capitalization for X|YData, sorry. I'm used to the days before the property names were made to be case-sensitive...personally, I think they still should be (case insensitive, that is), but The Mathworks didn't ask my opinion. :)
ADDENDUM:
I posted an alternate that shouldn't rely on saving the handles, but it isn't yet clear what is going bad with this...
ADDENDUM SECOND:
There isn't any other code that might be doing something else to the figure by any chance, is there? We only have the callback function to look at, if something elsewhere in the code is also trying to do graphics, all bets are off...
ADDENDUM THIRD:
The initialization code of @Walter Roberson will need either a try...catch...end block around the attempt to delete the handle variables or a test whether they have yet been created and are extant or not to avoid the error @Torsten showed.
I'm not positive what the examples posted by @Torsten are intended to show, the problems still remain about there being the multiple handles/objects in this case but only one in the MATLAB sample. Perhaps the brute-force technique showed above that returns the handle by calling subplot again each time will work similarly...
Torsten
il 12 Ago 2024
I just wanted to test whether your or @Walter Roberson 's plot functions are able to handle the case of two optimzation variables, but the aren't yet. I also included the master code from TMW for an optimization function in one unknown which works.
B. Burak
il 12 Ago 2024
Do you have a plot at the end of the 'init' phase? It appears should as both errorbar handles appear to exist.
We need to know what the rest of the workspace is in the 'iter' case...which i, what is value of numVars, what does
whos hEB
return, etc., etc., etc., ...???
If doesn't make sense from what we can see; something else is afoot besides...
ADDENDUM:
I wonder if making the given axis current again would solve the problem? Try adding in
...
case 'iter'
for i = 1:numVars
axes(hAx(i)); % make ith axex current
newX=[hEB(i).XData, generation]; % return existing data
...
Torsten
il 12 Ago 2024
Do you feel like me that it's really a mess with OutputFcn and PlotFcn functions in MATLAB ?
They really should be prepared for more user-friendly usage.
dpb
il 12 Ago 2024
I hadn't ever tried to use the PlotFcn so no experience, but it seems problematic given the conversation here, indeed.
Another of the cases of similar functionality but not overlapping -- the GA algorithm is in the Global Optimization TB, but not the Optimization TB. I didn't even know there was a "Global" one...one would think "Optimization" would mean optimization...
If I get some time, I might see if I can construct some sort of similar case with the TB have, but things are busy...
Mario Malic
il 12 Ago 2024
Wow, this blew up, always nice to see some community collaboration.
To me, the code looks okay. It doesn't sound possible that the hEB can be invalid or deleted (unless you closed the plot, which explains the error, but you probably didn't do that).
Suggestions:
- Try dbstop if error. When error happens inspect i variable and your hEB and hAx arrays, maybe you are trying to change property of an unitialized plot (graphic placeholder)
What would help is to describe plots you want to have. What does number of variables mean for plotting? Once you figure out that yourself, I think you should also supply axes as an input argument to your plotting functions, because they might overwrite what exists on the current axes which might lead to the invalid/deleted plot
@Mario Malic, the plots are described by the plotting function init routine -- an errorbar() plot for each of the N dimensions of the problem each as a Nx1 subplot().
The above reply by @B. Burak shows the two were created because hEB contains two errorbar objects although we weren't provided with screen shot nor description of what was/was not as expected initially -- only that it blows up after that -- although again, we don't yet know just what, precisely, it is that is the problem...we suspect it's one of the handles, but it isn't conclusive as yet with what debugging information has been provided.
It's looking more and more to me as though there must be some other plotting code in the rest of the code that we haven't seen or there is some magic behind the scenes in the optimization toolbox graphics callback code that is munging on the state of the graphics or there's some undocumented "feature" about persistent variables and callback functions...at the moment, not enough info to tell and I don't have the Global Optimization TB to try to create a GA call example...
B. Burak
il 12 Ago 2024
You mean there are no variables other than the options struct when the routine is called after the initial pass?
In that case, it's no wonder it doesn't work; nothing has/is being passed and the persistent variables aren't...that's something that 's not right in the calling sequence, not in the plotting function at all....
B. Burak
il 13 Ago 2024
Torsten
il 13 Ago 2024
From the documentation:
To display multiple plots, use a cell array of built-in plot function names or a cell array of function handles:
options = optimoptions('ga',...
'PlotFcn', {@plotfun1, @plotfun2, ...});
where @plotfun1, @plotfun2, and so on are function handles to the plot functions. If you specify more than one plot function, all plots appear as subplots in the same window. Right-click any subplot to obtain a larger version in a separate figure window.
I have no experience with PlotFcn, but maybe defining one function in your case doesn't suffice.
"...'iter' stage right before newX = [hEB(i).XData, generation]; ... I have them again, but they vanish with the error encountered."(*)
That's pretty-much conclusive evidence that the ga function is doing stuff behind the scenes that isn't documented and that is munging on the state of the HG environment, then.
I discovered the same thing in the documentation that @Torsten just commented on and was on my way here to post that tidbit as well; it appears trying to "roll your own" subplots is not feasible and you'll have to follow the documented route. This will be klunky if you are going to have very many possible values of N to have N subplots by having N different functions and list those specifically based on the value of N, but it appears may be the only way around the manner in which Mathworks has implemented the graphics callbacks.
Clever use of an array of function handles may make actual coding more generic than N unique, specific functions, but I've not thought about how(+); try the explicit two-function technique and get it to work first.
(*) I'd stop on entry to the CASE statement before continuing and then poke around in the debugger -- seeing what gca returns and comparing to the value(s) in the hAX array and looking for the children and all might be illuminating and it possibly could lead to being able to find out how to write code that will work, but if those handles are no longer valid references to the axes created in the initialization routine(**), something really peculiar is going on internally and there well may be no recourse at the user level to what MATLAB is doing internally that have no access to.
(+) Whether you can get clever and pass a cell array of elements set up programmatically, or whether it requires the explicit list, etc., etc., ... Like @Torsten, I've not ever used these callbacks so haven't ever investigated just how far can push. Apparently, we've found one limitation already...
(**) That may explain why all the sample code uses gca to retrieve the current axes object because the system internally will know what it is even if it has gotten reallocated and redefined internally from what it was originally by the time the iter call arrives. That, of course, would appear to be a potential problem if there is any other interaction going on while the optimization is running that could alter focus.
B. Burak
il 14 Ago 2024
dpb
il 14 Ago 2024
I did post a possible workaround in an earlier comment in the string that did not rely on the prior handles...you might try it; it tries to get at the existing subplots by addressing them with subplot(N,1,i) to return a temporary handle. However, if the internal code has, indeed, redefined the handles from the original, this also may not work.
ADDENDUM:
You know, it just came to me that there's one more adaptation of the code to try -- I realized just now that I forgot the
hold(hAx(i),'on')
in the initialization loop--I wonder if the fact that the 'NextPlot' property is still set to 'replace' is the cause of all the grief? Can't believe I didn't notice the oversight ere now; came because I retyped the code in the forum instead of copying test code... :(
Torsten
il 14 Ago 2024
If you could post your suggestion again, I could try to run it with the example given.
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
dpb
il 14 Ago 2024
First try with saving handles, including setting "hold on" would be
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;
persistent hAx hEb
switch flag
case 'init'
try % get rid of lingering objects if already extant
delete(hEB);
delete(hAx);
catch
end
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
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
The proposed alternate attempt for the 'iter' case was
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
Unfortunately no success with option 1:
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;
persistent hAx hEb
switch flag
case 'init'
try % get rid of lingering objects if already extant
delete(hEB);
delete(hAx);
catch
end
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
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
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
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...
Categorie
Scopri di più su Convert Image Type in Centro assistenza e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!









