Passing Extra Parameters in Optimization Output

5 vues (au cours des 30 derniers jours)
Oyeniyi
Oyeniyi le 8 Juin 2015
Commenté : HiWave le 15 Sep 2020
Is there a way to pass out extra calculated values (including the objective) from the objective function file while using the optimizers (e.g. fmincon, fminunc). For example in the code below, 'y' is the objective function to be minimized but I want the function to also return 'z' when the optimizer is called.
function [y z] = func(x,a,b,c)
y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) + ...
(-c + c*x(2)^2)*x(2)^2;
z = x(2)*x(1)^2 + b*x(2)^5;
end

Réponses (4)

Nicolas Lepage-Saucier
Nicolas Lepage-Saucier le 15 Déc 2017
It is better to avoid using global variables. A better way is to use extra input instead of extra output.
Step 1: Create a handle class (using a piece of code seen many places on forums)
Create a .m file named hObj.m and save it in your working directory:
classdef hObj < handle
properties
o=[];
end
methods
function obj=hObj(receivedObject)
obj.o=receivedObject;
end
end
end
Step 2: In your main file, create the handles that will receive your desired output, for instance:
y = hObj([]);
z = hObj([]);
Step 3: Add y_out and z_out as extra input of your optimization function and store their values in y_out.o and z_out.o:
function y = func(x,a,b,c,y_out,z_out)
y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) + ...
(-c + c*x(2)^2)*x(2)^2;
y_out.o = y;
z_out.o = x(2)*x(1)^2 + b*x(2)^5;
end
(note the .o that gives you access to the objects that y_out and z_out are pointing to).
Step 4: Add y and z to the input when calling the optimizer. For instance:
[x,fval] = fminunc(@(x)func(x,a,b,c,y,z),x0)
The whole code of the main file may look like this (note that prior to Matlab 2017, you may need to save your function func in a separate file, I'm not sure).
y = hObj([]);
z = hObj([]);
a = 4; b = 2.1; c = 4; % Assign parameter values
x0 = [0.5,0.5];
[x,fval] = fminunc(@(x)func(x,a,b,c,y,z),x0)
y.o
z.o
function y = func(x,a,b,c,y_out,z_out)
y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) + ...
(-c + c*x(2)^2)*x(2)^2;
y_out.o = y;
z_out.o = x(2)*x(1)^2 + b*x(2)^5;
end
  2 commentaires
Carlos Andrés Candelo Zuluaga
Thanks Man. This was useful for me.
HiWave
HiWave le 15 Sep 2020
BIG help...thanks!

Connectez-vous pour commenter.


Walter Roberson
Walter Roberson le 8 Juin 2015
No.
If I recall properly some error messages I have seen posted, the minimizers will check and will complain if you return extra outputs not configured by GradObj (second output) or Hessian (third output).
You could consider using an Output Function or Plot Function if what you wanted to do was display or plot current points or statistics.
However, if you want to output something computed along the way that, such as your z, then neither Output Functions nor Plot Functions are suitable, not directly.
You must already know how to parameterize objective functions, as otherwise you would not be receiving anything other than x for your objective function, no a, b, c. You can likewise parameterize Output Functions or Plot functions, and do the computation of z there and display or plot it.
If you want the values stored, then you will need to have your routine save the values somewhere, along with the current x. For example you could use nested routines to define your objective function, including shared variables that your objective function writes to. You can also do the same thing with global variables.
variable_to_save_to(end+1,:) = [z; x]; %scalar or column vector z
or
variable_to_save_to{end+1} = {x, z}; %any other kind of z

Yvan Denis
Yvan Denis le 11 Oct 2017
Modifié(e) : Walter Roberson le 11 Oct 2017
Juste for those who find that post in the futur: I know it's usually a bad idea but global variables could do the trick here.
global z
function [y z] = func(x,a,b,c)
y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) + ...
(-c + c*x(2)^2)*x(2)^2;
global z
z = [z x(2)*x(1)^2 + b*x(2)^5];
end
z store all the value obtained at each iteration.
  1 commentaire
Walter Roberson
Walter Roberson le 11 Oct 2017
You have a conflict there, between z as the output variable, and z as the global variable. In current releases, MATLAB will refuse to execute that code.
Also, as I indicated above, the optimizers check the number of output arguments and will complain if you return extra outputs beyond what might be required by using the GradObj or Hessian options.

Connectez-vous pour commenter.


Yaser Khojah
Yaser Khojah le 17 Mai 2018
I tried it but it shows the z value at the minimum point of y. Is there a way to show the value of z at all values of y; not only the minimum one.

Community Treasure Hunt

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

Start Hunting!

Translated by