# Constraint function in optimization toolbox

9 views (last 30 days)
Hussain Ja on 30 Jun 2020
Edited: Hussain Ja on 30 Jun 2020
I have the following main function which is connected with an external black box model through which Revenue of a plant is being maximized:
function varargout = EbsOptimize5_3(para)
para = reshape(para, 2, []);
Can I pass a constraint on minimum mass flow in a holding tank as follows:
c = -TotalmassFlow + 9.36e3;
ceq = [];
end
The solution is taking too long to converge and not giving a feasible point.

Matt J on 30 Jun 2020
Edited: Matt J on 30 Jun 2020
As far as I can see from your code, the mass flow constraint is linear in para. You would use the linear inequality constraint arguments to express it, and get rid of csp_advisor(),
Aineq=-ones(1,nvars);
bineq=-9.36e3/3600;
[x,fval,exitflag,output,population,score] = ...
ga(@EbsOptimize5_3,nvars,Aineq,bineq,[],[],lb,ub,[],[],options);

Hussain Ja on 30 Jun 2020
Shouldn't it be +9.36e3/3600?
It's converging fast now but the results are still the same.
I intentionally set a mass flow of 650*4(=flows)*3600 = 9.36e6 (I corrected for e6 in my program) but the solution always comes out to be [600;600;600;600].
Matt J on 30 Jun 2020
Shouldn't it be +9.36e3/3600?
No, because Aineq*x<=bineq written as a lower bound is -Aineq*x>=-bineq.
but the solution always comes out to be [600;600;600;600].
I cannot see anywhere in your code for EbsOptimize5_3 where para affects the TotalRevenue result. The TotalRevenue is calculated entirely based on other constants.
Hussain Ja on 30 Jun 2020
Thank you so much Matt. Now with -936e6/3600, I am getting better results and fast.
So 'para' affects 'Power' output (calculated by black box) which is multipled by tarrif rate of \$100 for first time period and by \$150 in the second time period.

Walter Roberson on 30 Jun 2020
The constraint function is passed the current value of all of the variables -- what you refer to as para in your main function. The constraint mechanism has no idea that one of the elements of para is acting as TotalMassFlow . You would have to extract TotalMassFlow out of para, such as
TotalMassFlow = para(9);
c = -TotalmassFlow + 9.36e3;
ceq = [];
end
However...
c = -TotalmassFlow + 9.36e3;
That is just an upper or lower bound on the element that represents TotalmassFlow. Do not implement upper or lower bounds through the nonlinear constraints: implement them through the lb and ub positions.
TotalmassFlow = sum(massFlow);
Oh, wait, TotalmassFlow is a calculated value, not one of the variables of optimization?? Calculated values are never passed into the nonlinear constraint function. The constraint function is passed only the current variables of optimization, para.
There is something crucial that you need to understand:
• The optimization routines do not call the nonlinear constraint function after every call to the objective function. If the previous location met constraints and the current location has a higher objective value than the old one, then regardless of whether the current location meets constraints or not, it is not going to be better than the old location. Also, the optimizers that estimate jacobians or hessians do not call the nonlinear constraints for the first several calls, while they gather enough information to estimate the jacobians.
• The optimization routines may call the nonlinear constraint function a number of times in a row without calling the objective function, especially if they have not yet found any point that is within constraints. Constraint functions are typically lower cost than the objective function, so it can make sense to find out whether a point is within constraints first before bothering to calculate the cost associated with the point
• Putting these together: when the nonlinear constraint function is called, you cannot count on it being called immediately after the call to the objective function with the same inputs, and when the objective function is called, you cannot count on it being called immediately after the call to the nonlinear constraint function with the same inputs. Therefore, mechanisms that work by storing the "latest" result from one for use in the other are not certain to work properly
• Since both your nonlinear constraint and objective function need to run the external model to build the values to calculate TotalmassFlow, you should put those calculations into a separate routine that you call from both functions
It appears likely that the calculation of TotalmassFlow is "expensive" in that it needs to activate an external program through a .NET assembly. You would like to avoid having to recalculate with the same parameters. But as described above, you cannot count on just saving the latest results from one for use in the other.
What to do for efficiency then? The answer is that when you put the calculations into a seperate routine, that you should memoize() the routine. memoize() is a layer that automatically builds a cache (that you can adjust the size of) on top of a function call, so that when it detects that the function is being calculated with the same arguments, it just pulls out the previous value instead of re-running the routine. Then it does not matter whether the separate function that invokes the external model got called first from the nonlinear constraints function or the objective function: the cache will be consulted and the result will be recalled either way. (You probably want the cache size to be larger than the population size.) The two routines do need to share the memoized handle, so you should either use a shared variable or else memoize first and pass that as an extra parameter into both the objective function and the nonlinear constraint function. http://www.mathworks.com/help/matlab/math/parameterizing-functions.html

#### 1 Comment

Hussain Ja on 30 Jun 2020
As suggested by Matt J above, since my constraint is a linear inquality equation, I can pass it as Aineq and bineq in the Optimization toolbox. This actually improved the convergence time but I am still getting unfeasible point as a solution i.e., [600;600;600;600] even though I intentionally chose to set mass flow as 650*4*3600 = 9.36e6, so the constraint violation between the massflows is (650-600)*4*3600=7.2e5, which is quite singnificant. For a simple problem like this shouldn't the algorithm atleast come close to the solution?

Translated by