I try to use an economic MPC for urban traffic (modelled as a state space system), to control the intersection's light.
I use fmincon for the optimization.
When I simulate it, I find that the fmincon runs more than one time for every sample time: for the first sample time, fmincon runs 32 times, the control value changes and Matlab shows me this message:
Initial point is a local minimum that satisfies the constraints.
Optimization completed because at the initial point, the objective function is non-decreasing in feasible directions to within the default value of the optimality tolerance, and constraints are satisfied to within the default value of the constraint tolerance.
stopping criteria details
After that, fmincon runs 2 times, the control value stays the same with the same matlab message.
Can I limit this run's number?
OK, you mixed-up a couple of topics:
MPC That stands for model predictive control, which is a control technique that solves an optimization problem at every sample point for a defined future horizon (by this it determines the control law implicitly, so you don't need to do the nasty pole-placement in Laplacian-space).
Anyway, you use fmincon to solve this optimization problem. If you go for runtime (so if it is a real-controller and not just a simulation) this is a bad choice since you have just a (potentially constrained but) linear optimization problem (state-space representation as you noted). Have a look here at Matlab doc on how to choose the ideal algorithm. For real implementations, I suggest to use the open-source library NLopt, which provides a nice Matlab interface and typically runs faster.
fmincon Now to your actual question: can one limit the calls of the objective function in fmincon? (Note that your term "run" is confusing as this refers to the starting of the optimization... as one would to over and over again in MPC. But you wanted to say "call of the objective function" as I guess)
The answer is yes.
opts = optimoptions('fmincon','MaxFunctionEvaluations',100);
[x,fval,exitflag] = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,opts)
Without code, it is hard to follow your specific problem, but the message (and probalb the exitflag) tells you that either your initial value or your objective-function sucks. fmincon doesn't find a direction in your parameter space, in which it can step for decreasing the value of your objective-function. The number of function-calls when it raisis this warning depends on the number of parameters length(x0) as the algorithm first needs wiggle a little at all parameters in all directions...
Thank you very much #max for your help and all this suggestion and information. About the controller, I use a real time simulation software with Matlab.
About the MPC, I use a non linear model, you can find the description here: https://www.sciencedirect.com/science/article/pii/S0968090X12000150
You're right about "call of the objective function", it's not "run".
I test the option that you suggest, the simulation is the same (same messages, same situation) I think that the problem is related with the number of "call of the objective function" for every sample time, not the number of the use of fmincon at all the simulation.
Your find below the function that I use for fmincon:
function u = solve(Np,x0,u0,Nu,q,ii)
u0 = [0];
Cycletime= 20/3600;
A = [];
b = [];
Aeq = [];
beq = [];
lb = [];
ub = [];
lbx = [];
ubx = [];
lbu = [];
ubu = [];
lx = 0;
ux = 386;
lu = 0;
uu = Cycletime;
lbx = [lbx, lx];
ubx = [ubx, ux];
lbu = [lbu lu];
ubu = [ubu uu];
lb = [lbu ;lbx];
ub = [ubu ;ubx];
% Solve optimization problem
u = fmincon(#(u)costfunction1(x0,u,Nu,Np,q,ii), u0, A, b, Aeq, beq, lb,ub) ;
end
Related
I have an integer programming optimization problem, that I solve in matlab using yalmip and xpress as the solver. For the solver I want to set two stopping criteria - a time limit and an optimal gap limit.
I have tried to use the xpress functions MAXTIME and MIPRELSTOP, the matlab code compiles and runs the optimization but the stopping criteria are not transferred to the solver.
The relevant code part looks as follows:
Cons = [sum(sum((dVar_mat.*(x_mat.*y_vec))')) >= a]; %constraint
obj = sum(sum(dVar_mat.*z_mat)); %objective
ops = sdpsettings('solver', 'xpress', 'verbose', 2); %solver options
ops.xpress.MAXTIME = 10000; %set timelimit
ops.xpress.MIPRELSTOP = 0.05; %set relative gap as stop limit
solIP = optimize(Cons, obj, ops); % Solve
When I run the optimzation, a solution is found but significantly later than I would like it to stop. The report says:
STOPPING - MIPRELSTOP target reached (MIPRELSTOP=0.0001)
meaning the MIPRELSTOP target is still set at the default, which is 0.0001. Similarily, the optimization runs over the time limit, disregarding that stopping criterion as well.
How can I correctly set stopping criteria in matlab/yalmip/xpress?
Are you sure you are using the correct name and that it is exposed in the MATLAB interface, i.e. is that options visible in ops.xpress. I don't have xpress installed so I cannot test it.
(btw, YALMIP question are much better asked on the YALMIP Google groups forum)
The 'MAXTIME' control of Xpress Optimizer can be used with positive and negative values: with positive values for 'MAXTIME' when solving MIP problems the limit is only applied once a solution has been found, otherwise the solving continues until the first solution is found; a negative value means a hard stop, so for your case I would recommend that you try a value like -10000 as the time limit.
(See the documentation in the Xpress Optimizer Reference Manual, eg: https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/HTML/MAXTIME.html)
I run a Matlab code with an iteration loop, and during each iteration it sample random numbers and uses the function intlinprog. My issue is that, due to the large amount of data I provide to the intlinprog function and to the stochastic values I assign to part of its variables, some of the iterations take a really long time.
My code is more or less like this:
rounds = 1E3;
Total_PF = zeros(rounds,4893);
for i=1:rounds
i
cT = zeros (4894,1);
cT(4894,1) = 1;
xint = linspace(1,4893,4893);
xint = xint';
AT = rand(4,4894);
beT = ones(4,1);
lb = zeros(4894,1);
ub = ones (4894,1);
ub(4894,1) = Inf;
[x] = intlinprog(cT,xint,AT,beT,[],[],lb,ub);
Total_PF(i,:)= (x(1:length(x)-1)');
end
Now in the minimal working example I provided, all the iterations are quite fast, but in my real code, sometimes intlinprog takes really long time ( I mean hours) to do a single iteration.
Therefore, I was wondering: is there a way to break the intlinprog while the intlinprog line is being executed? I was thinking that it may be done by modifying the matlab function but first of all I do not know if I am allowed to do it, secondly I am afraid that may be very dangerous.
This is very difficult to do effectively.
You could try using a timer object to watch the value. However, since you are using inherent Matlab functions and not executing external functions, you could set a time limit value and utilize tic and toc in a while loop while you execute the intlinprog and checking the value of toc against your time limit and break your code if toc exceeds the limit.
I have to iterate a process where I have an initial guess for the Mach number (M0). This initial guess will give me another guess for the Mach number by using two equations (Mn). Eventually, i want to iterate this process untill the error between M0 and Mn is small. I have the following piece of code and it actually works well with a while loop.
However, I am afraid that the while loop will take many iterations and computational time for certain inputs since this will be part of a bigger code which most likely will give unfeasible inputs for the while loop.
Therefore my question is the following. How can I iterate this process within Matlab without consulting a while loop? The code that I am implementing now is the following:
%% Input
gamma = 1.4;
theta = atan(0.315);
cpi = -0.732;
%% Loop
M0 = 0.2; %initial guess
Err = 100;
iterations = 0;
while Err > 0.5E-3
B = (1-(M0^2)*(1-M0*cpi))^0.5;
Mn = (((gamma+1)/2) * ((B+((1-cpi)^0.5)*sec(theta)-1)^2/(B^2 + (tan(theta))^2)) - ((gamma-1)/2) )^-0.5;
Err = abs(M0 - Mn);
M0 = Mn;
iterations=iterations+1;
end
disp(iterations) disp(Mn)
Many thanks
Since M0 is calculated in each iteration and you have trigonometric functions, you cannot use another way than iteration structures (i.e. while).
If you had a specific increase or decrease at M0, then you could initialize a vector of M0 and do vector calculations for B and Err.
But, with sec and tan this is not possible.
Another wat would be to use the parallel processing. But, since you change the M0 at each iteration then you cannot use the parfor loop.
As for a for loop, in MATLAB you need an array for for "command" argument (e.g. 1:10 or 1:length(x) or i = A, where A = 1:10 or A = [1:10;11:20]). Since you evaluate a condition and depending on the result of the evaluation you judge if you continue the execution or not, it seems that the while loop (or do while in another language) is the only way to go.
I think you need to clarify the issue. If it the issue you want to solve is that some inputs take a long time to calculate, it is not the while loop that takes the time, it is the execution of the code multiple times that causes it. Any method that loops through will be restricted by the time the block of code takes to execute multiplied by the number of iterations required to converge.
You can introduce something to stop at a certain number of iterationtions, conceptually:
While ((err > tolerance) && (numIterations < limit))
If you want an answer which does not require iterating over the code, this is akin to finding a closed form solution, and I suspect this does not exist.
Edit to add: by not exist I mean in a practical form which can be implemented in a more efficient way then iterating to a solution.
How can the output.stepsize be used as a stopping criterion for fmincon when using the 'active-set' algorithm?
When I tried to solve a nonlinear constrained non-convex optimization problem, I observed that the output.stepsize option within 'PlotFcns' would be a better stopping criterion than the tolerances or maximum evaluations. But in the options argument structure, there is no such option.
I also noticed that fmincon uses nonlcon to solve the problem where output.stepsize is calcualted.
If I don't want to change the original code of either fmincon or nonlcon, how can I set an upper limit for output.stepsize to use as a stopping criterion for my optimization run?
Here's one way that you might try to accomplish this. I'm using one of the examples from the doc (there's also discussion of how to do exactly this there as well). I've simply added an output function that returns stop = true when the optimValues.stepsize field reaches a threshold. I also had to make sure that this field wasn't empty, as it appears to be at initialization.
function fmincontest
A = [-1 -2 -2;
1 2 2];
b = [0;72];
x0 = [10;10;10];
options = optimoptions('fmincon','Algorithm','active-set','OutputFcn',#outfun);
[x,fval,exitflag] = fmincon(#myfun,x0,A,b,[],[],[],[],[],options)
function f = myfun(x)
f = -x(1)*x(2)*x(3);
function stop = outfun(x, optimValues, state)
stop = ~isempty(optimValues.stepsize) && optimValues.stepsize < 0.05;
If you check the exit_flag output from fmincon, you'll see that it returns -1 now because the output function is stopping the optimization, again as indicated in the documentation. If you're already using a plot function, you can use that instead, as they have the same format.
You'll need to tailor this to your problem, adjust the threshold, and of course confirm that it works. I can't comment on how good of an idea this is. You should confirm that your error tolerances are still met satisfactorily for all cases. And I'd still want to ask why you can't specify appropriate 'TolCon' and 'TolX' tolerances to achieve what you need.
I was reading this post online where the person mentioned that using "if statements" and "abs()" functions can have negative repercussions in MATLAB's variable-step ODE solvers (like ODE45). According to the OP, it can significantly affect time-step (requiring too low of a time step) and give poor results when the differential equations are finally integrated. I was wondering whether this is true, and if so, why. Also, how can this problem be mitigated without resorting to fix-step solvers. I've given an example code below as to what I mean:
function [Z,Y] = sauters(We,Re,rhos,nu_G,Uinj,Dinj,theta,ts,SMDs0,Uzs0,...
Uts0,Vzs0,zspan,K)
Y0 = [SMDs0;Uzs0;Uts0;Vzs0]; %Initial Conditions
options = odeset('RelTol',1e-7,'AbsTol',1e-7); %Tolerance Levels
[Z,Y] = ode45(#func,zspan,Y0,options);
function DY = func(z,y)
DY = zeros(4,1);
%Calculate Local Droplet Reynolds Numbers
Rez = y(1)*abs(y(2)-y(4))*Dinj*Uinj/nu_G;
Ret = y(1)*abs(y(3))*Dinj*Uinj/nu_G;
%Calculate Droplet Drag Coefficient
Cdz = dragcof(Rez);
Cdt = dragcof(Ret);
%Calculate Total Relative Velocity and Droplet Reynolds Number
Utot = sqrt((y(2)-y(4))^2 + y(3)^2);
Red = y(1)*abs(Utot)*Dinj*Uinj/nu_G;
%Calculate Derivatives
%SMD
if(Red > 1)
DY(1) = -(We/8)*rhos*y(1)*(Utot*Utot/y(2))*(Cdz*(y(2)-y(4)) + ...
Cdt*y(3)) + (We/6)*y(1)*y(1)*(y(2)*DY(2) + y(3)*DY(3)) + ...
(We/Re)*K*(Red^0.5)*Utot*Utot/y(2);
elseif(Red < 1)
DY(1) = -(We/8)*rhos*y(1)*(Utot*Utot/y(2))*(Cdz*(y(2)-y(4)) + ...
Cdt*y(3)) + (We/6)*y(1)*y(1)*(y(2)*DY(2) + y(3)*DY(3)) + ...
(We/Re)*K*(Red)*Utot*Utot/y(2);
end
%Axial Droplet Velocity
DY(2) = -(3/4)*rhos*(Cdz/y(1))*Utot*(1 - y(4)/y(2));
%Tangential Droplet Velocity
DY(3) = -(3/4)*rhos*(Cdt/y(1))*Utot*(y(3)/y(2));
%Axial Gas Velocity
DY(4) = (3/8)*((ts - ts^2)/(z^2))*(cos(theta)/(tan(theta)^2))*...
(Cdz/y(1))*(Utot/y(4))*(1 - y(4)/y(2)) - y(4)/z;
end
end
Where the function "dragcof" is given by the following:
function Cd = dragcof(Re)
if(Re <= 0.01)
Cd = (0.1875) + (24.0/Re);
elseif(Re > 0.01 && Re <= 260.0)
Cd = (24.0/Re)*(1.0 + 0.1315*Re^(0.32 - 0.05*log10(Re)));
else
Cd = (24.0/Re)*(1.0 + 0.1935*Re^0.6305);
end
end
This is because derivatives that are computed using if-statements, modulus operations (abs()), or things like unit step functions, dirac delta's, etc., will introduce discontinuities in the value of the solution or its derivative(s), resulting in kinks, jumps, inflection points, etc.
This implies the solution to the ODE has a complete change in behavior at the relevant times. What variable step integrators will do is
detect this
recognize that they won't be able to use information directly beyond the "problem point"
decrease the step, and repeat from the top, until the problem point satisfies the accuracy demands
Therefore, there will be many failed steps and reductions in step size near the problem points, negatively affecting the overall integration time.
Variable step integrators will continue to produce good results, however. Constant step integrators are not a good remedy for this sort of problem, since they are not able to detect such problems in the first place (there's no error estimation).
What you could do is simply split the problem up in multiple parts. If you know beforehand at what points in time the changes will occur, you just start a new integration for each interval, each time using the output of the previous integration as the initial value for the next one.
If you don't know beforehand where the problems will be, you could use this very nice feature in Matlab's ODE solvers called event functions (see the documentation). You let one of Matlab's solvers detect the event (change of sign in the derivative, change of condition in the if-statement, or whatever), and terminate the integration when such events are detected. Then start a new integration, starting from the last time and with initial conditions of the previous integration, as before, until the final time is reached.
There will still be a slight penalty in overall execution time this way, since Matlab will try to detect the location of the event accurately. However, it is still much better than running the integration blindly when it comes to both execution time and accuracy of the results.
Yes it is true and it happens because of your solution is not smooth enough at some points.
Assume you want to integrate. y'(t) = f(t,y). Then, what happens in f is getting integrated to become y. Thus, if in your definition of f there is
abs(), then f has a kink and y is still smooth and 1 times differentiable
if, then f has a jump and y a kink and no more differentiability
Matlab's ODE45 presumes that your solution is 5 times differentiable, and tries to ensure an accuracy of order 4. Nonsmooth points of your function are misinterpreted as stiffness what leads to small stepsizes and even to breakdowns.
What you can do: Because of the lack of smoothness you cannot expect a high accuracy anyways. Thus, ODE23 might be a better choice. In the worst case, you have to stick to first-order schemes.