Passing Extra Parameters in Optimization Output

9 views (last 30 days)
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

Answers (4)

Nicolas Lepage-Saucier
Nicolas Lepage-Saucier on 15 Dec 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

Walter Roberson
Walter Roberson on 8 Jun 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 on 11 Oct 2017
Edited: Walter Roberson on 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 Comment
Walter Roberson
Walter Roberson on 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.

Sign in to comment.


Yaser Khojah
Yaser Khojah on 17 May 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!