How to display the value of a specific component of the objective function after computation is done?

Good evening,
I was looking through Matlab documentation for genetic algorithm and I found the following example: "Plan Nuclear Fuel Disposal Using Multiobjective Optimization" https://www.mathworks.com/help/gads/multiobjective-nuclear-fuel-disposal.html
After reading through that example, I have a question. Is it possible to display/know the value of a specific component of the objective function for a certain point on the Pareto front after the computation is over?
For instance, if I want to know the value of the objective function "cost" for the first point on the front, the command is:
display(sol(1).cost)
But through this command I get the total cost calculated for the first point.
What if I want to know the value for the third cost component? Is there any way to determine it or not? I tried the following: display(sol(1).cost(3)) but apparently it doesn't work.
Do you have any pointers?
I hope my question is clear. If you need any clarification let me know. I will gladly answer any question and I will be really thankful for any suggestions.
Kind regards,
William

2 Comments

(I am trying to investigate this, but the script is running very slowly on my machine :( :( :( )
@Walter Roberson unfortunately, I'm aware that that script runs very slowly. In the meantime I tried looking everywhere for similar questions but I couldn't find anything. Please, let me know if you manage to find out something about it. I will greatly appreciate it.

Sign in to comment.

 Accepted Answer

I'd be very interested to know what you think of the nuclear fuel disposal example.
But to answer your question, let's look at an example that is faster to compute.
x = optimvar("x",1,2,LowerBound=-50,UpperBound=50);
fun(1) = x(1)^4 + x(2)^4 + x(1)*x(2) - x(1)^2*x(2)^2 - 9*x(1)^2;
fun(2) = x(1)^4 + x(2)^4 + x(1)*x(2) - x(1)^2*x(2)^2 + 3*x(2)^3;
prob = optimproblem("Objective",fun);
rng default % For reproducibility
sol = solve(prob)
Solving problem using gamultiobj. Optimization terminated: average change in the spread of Pareto solutions less than options.FunctionTolerance.
sol =
1×18 OptimizationValues vector with properties: Variables properties: x: [2×18 double] Objective properties: Objective: [2×18 double]
Look at the two objective components at the first solution point.
t = sol(1).Objective
Cannot find function "solution.mlx".

Error in ()
Look at just the second objective component at the first solution point.
ob = sol(1).Objective(2)
This is exactly what you tried, and it works fine for me.
Alan Weiss
MATLAB mathematical toolbox documentation

13 Comments

The nuclear fuel disposal example is very clear.
Going back to that example (just to be sure I understood your answer): what you're saying is that if I want to know both the total value of the objective function "cost" and the value of one of its components separately from all the rest (let's say cost of canisters, i.e. cost(4)) for a certain solution point I can do that?
By "component of the objective function" I don't mean two different objective functions but two different addendums that appear in the expression of the same objective function.
Oh, sorry, I didn't understand before that what you wanted was just one of the portions of the seven items that go into making the cost. Those items are not maintained as separate components in the example.
What you can do is recompute the cost items separately after the solver is done, or you can make a slight modification to the solution process by using an output function or plot function to show those things as the slow iterations proceed. To recompute, just feed the returned solution into the cost expression.
mycost = evaluate(cost,sol(1));
disp(mycost(3))
I haven't tried this, but it should work.
And I'm glad to hear that you found the nuclear fuel example clear. It was a lot of work to make that example and I have heard almost no feedback on it.
Alan Weiss
MATLAB mathematical toolbox documentation
@Alan Weiss thank you for the answer! As soon as the computation for my problem is done I'll try the recompute route and let you know.
That example was really useful because I used that approach to develop my master's degree thesis on a different optimization model. And the last step was to do an analysis like the following: for solution 1 the total cost is 100, of which 37 is the cost of canisters, 42 is the cost of disposal etc. Basically, after optimizing the objective function, I wanted to evaluate how each term contributed to the total.
I hope your suggestion will turn out to be useful for me. If that's the case I'll update you and accept/vote your answer.
In the meantime, thank you so much for reading through my post and taking your time to figure out a way to solve the issue. You were really kind.
William
@Alan Weiss Good morning, I tried this method but I received the following error message: "error using optim.problemdef.OptimizationExpression/evaluate. Second argument must be nonempty struct."
you would get that message if solve() was not able to find a solution.
@Walter Roberson but how is that possible? I got 11 solutions from solve().
If I use display(sol) I get this:
sol =
1×11 OptimizationValues vector with properties:
Variables properties:
alpha: [5-D double]
beta: [5-D double]
gamma: [5-D double]
s: [5×6×11×11 double]
sigma: [5-D double]
w: [5×9×11×11 double]
Objective properties:
psi_time: [355.2000 386.0000 423.0000 444.3000 482.8000 590.1000 506.6000 … ]
psi_energy: [6.0263e+03 5.8362e+03 5.1067e+03 4.8756e+03 4.7247e+03 … ]
Constraints properties:
cons2: [5-D double]
cons6: [5×6×11×11 double]
cons7: [5×9×11×11 double]
cons8: [6×11×11 double]
cons9: [5×11×11 double]
cons10: [5-D double]
cons11: [5-D double]
cons12: [6×11×11 double]
cons13: [5-D double]
cons1: [1×9×11×11 double]
cons3: [5×1×11×11 double]
So I suppose it managed to find several solutions.
However, if I click on "sol" in the workspace, I first get a 1x11 matrix and in each cell "1x11 OptimizationValues", by clicking on a single cell I then get an empty sol(1,1). But this thing happened with the several examples I ran without changing the code so I thought it was something that happened regularly.
All the other commands work just fine. For instance, if I write display(sol(1).psi_time) I get the correct value for objective psi_time at solution point 1. Same goes if I display the values of the decision variables for a certain solution point.
So I don't really understand where the issue lies.
Mea culpa. I forgot that the returned points from solve for a multiobjective problem is not a structure but is, instead, an OptimizationValues vector. The evaluate function expects that the points you include to be in a structure, not an OptimizationValues object.
So one thing to do is to turn your returned solution point into a structure instead of an object before feeding it into evaluate. Something like:
vv = sol(1);
ss.alpha = vv.alpha;
ss.beta = vv.beta;
ss.gamma = vv.gamma;
ss.s = vv.s;
ss.w = vv.w;
ss.sigma = vv.sigma;
mycost = evaluate(cost,ss)
Again, sorry for my oversight. If I come up with a better way to turn the returned object into a struct, I'll let you know.
Alan Weiss
MATLAB mathematical toolbox documentation
Hmm, there is a rather ugly workaround:
vv = sol(1);
vstruct = struct(vv); % Throws a warning, don't be alarmed
mycost = evaluate(cost,vstruct.Values)
If I find anything better, I'll let you know.
Alan Weiss
MATLAB mathematical toolbox documentation
@Alan Weiss thank you so much Alan. The first approach you proposed works perfectly. You've been really helpful and I'm extremely grateful!
I have just one last question: if beta is a 5x6x6x11 binary variable that specifies whether a system reconfiguration is executed or not at a certain time period, by using the command: display[sum(sol(1).beta,'all')], what I get as the answer is the total numer of '1' for beta, i.e. the total number of reconfiguration executed for all periods, is that correct or with that command there may be some '1' that are counted more than once?
Also, how do I accept the exact comment that answered my question? The "accept answer" button only appears next to your first comment. Or should I just accept that one since it's the beginning of your thread?
William
The only way to accept any part of my answer is to accept the whole thing. That's just the way it is when I answer in a long thread like this.
I believe that your command is the correct way to count the number of beta variables that have the value 1. If it comes back as 1, well, I bet if you print out all of the values you will find just one 1.
Alan Weiss
MATLAB mathematical toolbox documentation
display[sum(sol(1).beta,'all')] is not going to work. maybe
display(sum(sol(1).beta,'all'))
But if so you would get a warning about not calling display yourself.
You should also consider using nnz() instead of sum for this purpose
@Walter Roberson thank you for your suggestions. They work perfectly as intended.
Have a good day!

Sign in to comment.

More Answers (0)

Products

Release

R2022b

Asked:

on 20 Jan 2023

Commented:

on 30 Jan 2023

Community Treasure Hunt

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

Start Hunting!