My Genetic Algorithm optimization script on Matlab runs, but at the end produces the following message: "Optimization terminated: average change in the penalty fitness value less than options.TolFun but constraints are not satisfied."
Why would it say that? I replaced my fitness function with one that does nothing but returns a constant number, and nothing changed. It may be the case that my constraints are not defined correctly, though I can't find the mistake. Here is the relevant part of the code:
nGenerators = 9;
monthlyHours = 24*daysInJanuary;
(some irrelevant code here)
steamCapacities = [31.46*ones(1,2) 5.5*ones(1,3) 4*ones(1,4)];
nVars = xSize;
IntCon = 1:nVars;
LB = zeros(1, nVars);
UB = ones(1, nVars);
b = -1*steamLoad; % Ax <= b
A = zeros(monthlyHours, xSize);
for p = 1:monthlyHours
A(p, 9*p-8:9*p) = -1*steamCapacities;
% disp(p);
end
(some more code here)
anonFitness = #(x)mosb_test(x, fitnessData);
gaOptions = gaoptimset('Vectorized', 'off', 'UseParallel', 'always', ...
'Display', 'diagnose', 'PlotFcn', #gaplotbestf, 'Generations', 300, ...
'TolFun', 1e-15, 'StallGenLimit', 200);
[x, fval, exitFlag] = ga(anonFitness, nVars, A, b,[],[], LB, UB, [], IntCon, gaOptions);
Here, x represents the on/off states for a set of 9 generators for each hour of the month. Their steam production capacities are as in the variable steamCapacities, and there is a constant steam load that has to be met at every hour. This is represented by the inequality constraint.
Any help appreciated.
Interesting problem! Too bad it can't be solved deterministically. :-( Anyway, your TolFun is defined by the mathworks as being:
Positive scalar. The algorithm stops if the weighted average relative
change in the best fitness function value over StallGenLimit
generations is less than or equal to TolFun
and StallGenLimit has the same description. It makes perfect sense that a constant will give you the same error. It appears to me that the GA is unable to converge to a solution in the StallGenLimit, here 200, generations. You could try making the TolFun more restrictive, like 1e-12, or try and develop a far simpler model for the GA, one that will just allow you to find a solution. Then build complexity on this model until it matches your real system. Likely, it will fail at some point and you will be able to see why the problem can't be solved like too many degrees of freedom, too tight of constraints, etc. HTH!
Related
How would I numerically solve for the following simple system of differential equations using Octave?
Note:
I use the qualifier "simple" as, from my understanding, the system is
first order and is not coupled.
I have tried every
method and script online to try solve this including here,
here and here. In all options, I either get a hanging,
non-responsive Octave, a prompt stating "repeated convergence
failures", an error with recommendation that I manually adjust
the initial and maximum step size (which I did try and do, to no
avail), or something that initially seems like a solution on account of no errors but plotting the solution shows a blank graph
Where Octave provided for equivalent Matlab routines, I tried the various routines ode45, ode23, ode113, ode15s, ode23s, ode23t, ode23tb, ode15i and of course, Octaves own lsode command, all giving the same errors described above.
Let's first replicate the vanilla solution
% z = [x,y]
f = #(t,z) [ z(1).^2+t; z(1).*z(2)-2 ];
z0 = [ 2; 1];
[ T, Z ] = ode45(f, [0, 10], z0);
plot(T,Z); legend(["x";"y"]);
The integrator fails as reported with the warning
warning: Solving was not successful. The iterative integration loop exited at time t = 0.494898 before the endpoint at tend = 10.000000 was reached. This may happen if the stepsize becomes too small. Try to reduce the value of 'InitialStep' and/or 'MaxStep' with the command 'odeset'.
Repeating the integration up to shortly before the critical time
opt = odeset('MaxStep',0.01);
[ T, Z ] = ode45(f, [0, 0.49], z0, opt);
clf; plot(T,Z); legend(["x";"y"]);
results in the graph
where one can see that the quadratic term in the first equation leads to run-away growth. For some reason the solver does only recognize the ever reducing step size, but not the run-away values of the solution.
Indeed the first is a Riccati equation which are known to have poles at finite times. Using the typical parametrization x(t)=-u'(t)/u(t) has by the product/quotient rule the derivative
x' = -u''(t)/u(t) - u'(t)* (-u'(t)/u(t)^2) = -u''(t)/u(t) + x(t)^2
which then results in the ODE for u
u''(t)+t*u(t)=0, u(0)=-1, u'(0)=x(0)=2,
which is an Airy equation with the oscillating branch for t>0. The first root of u is a pole for x, there is no way to extend the solution beyond this point.
g=#(t,u) [u(2); -t.*u(1)]
u0 = [ 1; -2];
function [val,term, dir] = event(t,u)
val = u(1);
term = 0;
dir = 0;
end
opt = odeset('MaxStep',0.1, 'Events', #(t,u) event(t,u));
[T,U,Te,Ue,Ie] = ode45(g,[0,4],u0,opt);
disp(Te)
clf; plot(T,U); legend(["u";"u'"]);
which lists the zeros of u as 0.4949319379979706, 2.886092605590324, again confirming the reason for the warning, and gives the plot
I'm currently trying to use fmincon in Matlab.
I can get it to operate correctly, but this falls over when i include manipulation of matrix elements which don't meet a condition.
As below
ub = 1.1;
lb = -1.2;
aut = -0.25;
h = #(aut)eQ_Optim(aut);
u = fmincon(h,aut, [], [], [], [], lb, ub)
The function i'm using is as follows
function [Maxim] = eQ_Optim(aut);
Data = [-0.23183483,-0.003274012;
-0.289945477,0.000282334;
-0.483591973,0.006588649;
-0.257735378,0.000887691;
-0.286463622,-0.003235662;
-0.453939127,0.004358216;
-0.196363243,0.004186609;
-0.209783591,0.001715187];
Data(Data(:,1)<aut,2)=0
MDOnx=Data(:,2)+1;
MD_Cumx=cumprod(MDOnx,1);
Maxim = MD_Cumx(end)*-1
end
I'm trying to get fmincon to optimise the variable 'aut', such that it maximises the cumulative sum of the right hand column (Data(:,2)).
for reference, the output i'm receiving is
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.
u =
-0.250000000000000
Which as you can see, is just my original guess being fed back to me.
I hope everything is clear. I've simplified everything as much as possible. Is this possible?
The solution was to use fminbid with applicable intervals
% % % https://uk.mathworks.com/help/matlab/ref/fminbnd.html
In my opinion, fmincon is a built-in function for local minimum in matlab. If the objective function is a convex problem, there is only one basin and the local minimum is the global minimum. While starting from different initial points in my experiment, the algorithm got different minimums function. I wonder if fmincon guarantees to be converged to a global minimum for convex problem. If not, is there any other techiniques I can use for convex opimization as fast as possible? Thanks.
P.S. fmincon use interior-point-method for searching minimum in default. Is this a normal problem for interior-point method, that is ,starting from different intial point, the method can get different global minimum for convex problem?
EDIT:
The objective is to minimize the sum of energy consumption by a group of users in a communication process, while the allocation of bandwidth is search. The transmission rate is
$r_k = x_k * log_2(1+\frac{g_k*p_k}{x_k})$
The optimization problem is as follow
$min_{x} sum_k \frac{p_k*b_k}{r_k}$
s.t. $sum_k x_k \leq X_{max}$
The objective and constraints are all convex, thus this should be a convex optimization problem.
For programming code, it is just as follow,
options = optimoptions('fmincon');
problem.options = options;
problem.solver = 'fmincon';
problem.objective = #(x) langBW(x, in_s, in_e, C1, a, p_ul);
problem.Aineq = ones(1,user_num);
problem.bineq = BW2;
problem.nonlcon = #(x) nonlConstr_bw(x,a,p_ul,T1,in_s,in_e,BW2);
problem.x0 = ones(user_num,1)
[b_ul,fval] = fmincon(problem);
langBW is the objective function, which is a convex function of x, the code of langBW is as follow,
function fmin = langBW(x, in_s, in_e, C1, a, p_ul)
if size(x,1)<size(x,2)
x = x';
end
b_ul = x;
r_ul = b_ul .* log2(1 + a.*p_ul./b_ul);
fmin = sum((in_s+in_e).*p_ul./r_ul) + sum(C1);
end
The nonlConstr_bw is the function of nonlinear constraints. It is shown as follow,
function [c,ceq] = nonlConstr_bw(x,a,p_ul,T1,in_s,in_e)
user_num = size(p_ul,1);
if size(x,1)<size(x,2)
x = x';
end
b_ul = x;
r_ul = b_ul .* log2(1 + a.*p_ul./b_ul);
c1 = max(in_s./r_ul) + in_e./r_ul - T1;
c = c1;
ceq = zeros(user_num,1);
end
Except x, all other variables are supplied. The problem is that when I set different problem.x0, for example, when problem.x0=ones(user_num,1);, the solution of [b_ul,fval] = fmincon(problem); is different from that when problem.x0=2*ones(user_num,1);. That is what I am confused about.
fmincon uses the following algorithms:
'interior-point' (default)
'trust-region-reflective'
'sqp' (Sequential Quadratic Programming)
'sqp-legacy'
'active-set'
These methods will converge to a local minimia but not necessarily a global minimum. Further minima may not be unique. The only way to guarantee a global minima is to search the whole solution space.
From your comment, there appears to be only a signal minima? (For example, a shifted parabola?) Then it should converge.
edit--
Even if your function appears convex, the constraints can lead to multiple local minima. Sometimes this is called a "loosely" convex function
I have an integrated error expression E = int[ abs(x-p)^2 ]dx with limits x|0 to x|L. The variable p is a polynomial of the form 2*(a*sin(x)+b(a)*sin(2*x)+c(a)*sin(3*x)). In other words, both coefficients b and c are known expressions of a. An additional equation is given as dE/da = 0. If the upper limit L is defined, the system of equations is closed and I can solve for a, giving the three coefficients.
I managed to get an optimization routine to solve for a purely based on maximizing L. This is confirmed by setting optimize=0 in the code below. It gives the same solution as if I solved the problem analytically. Therefore, I know the equations to solve for the coefficent a are correct.
I know the example I presented can be solved with pencil and paper, but I'm trying to build an optimization function that is generalized for this type of problem (I have a lot to evaluate). Ideally, polynomial is given as an input argument to a function which then outputs xsol. Obviously, I need to get the optimization to work for the polynomial I presented here before I can worry about generalizations.
Anyway, I now need to further optimize the problem with some constraints. To start, L is chosen. This allows me to calculate a. Once a is know, the polynomial is a known function of x only i.e p(x). I need to then determine the largest INTERVAL from 0->x over which the following constraint is satisfied: |dp(x)/dx - 1| < tol. This gives me a measure of the performance of the polynomial with the coefficient a. The interval is what I call the "bandwidth". I would like to emphasis two things: 1) The "bandwidth" is NOT the same as L. 2) All values of x within the "bandwidth" must meet the constraint. The function dp(x)/dx does oscillate in and out of the tolerance criteria, so testing the criteria for a single value of x does not work. It must be tested over an interval. The first instance of violation defines the bandwidth. I need to maximize this "bandwidth"/interval. For output, I also need to know which L lead to such an optimization, hence I know the correct a to choose for the given constraints. That is the formal problem statement. (I hope I got it right this time)
Now my problem is setting this whole thing up with MATLAB's optimization tools. I tried to follow ideas from the following articles:
Tutorial for the Optimization Toolbox™
Setting optimize=1 for the if statement will work with the constrained optimization. I thought some how nested optimization is involved, but I couldn't get anything to work. I provided known solutions to the problem from the IMSL optimization library to compare/check with. They are written below the optimization routine. Anyway, here is the code I've put together so far:
function [history] = testing()
% History
history.fval = [];
history.x = [];
history.a = [];
%----------------
% Equations
polynomial = #(x,a) 2*sin(x)*a + 2*sin(2*x)*(9/20 -(4*a)/5) + 2*sin(3*x)*(a/5 - 2/15);
dpdx = #(x,a) 2*cos(x)*a + 4*cos(2*x)*(9/20 -(4*a)/5) + 6*cos(3*x)*(a/5 - 2/15);
% Upper limit of integration
IC = 0.8; % initial
LB = 0; % lower
UB = pi/2; % upper
% Optimization
tol = 0.003;
% Coefficient
% --------------------------------------------------------------------------------------------
dpda = #(x,a) 2*sin(x) + 2*sin(2*x)*(-4/5) + 2*sin(3*x)*1/5;
dEda = #(L,a) -2*integral(#(x) (x-polynomial(x,a)).*dpda(x,a),0,L);
a_of_L = #(L) fzero(#(a)dEda(L,a),0); % Calculate the value of "a" for a given "L"
EXITFLAG = #(L) get_outputs(#()a_of_L(L),3); % Be sure a zero is actually calculated
% NL Constraints
% --------------------------------------------------------------------------------------------
% Equality constraint (No inequality constraints for parent optimization)
ceq = #(L) EXITFLAG(L) - 1; % Just make sure fzero finds unique solution
confun = #(L) deal([],ceq(L));
% Objective function
% --------------------------------------------------------------------------------------------
% (Set optimize=0 to test coefficent equations and proper maximization of L )
optimize = 1;
if optimize
%%%% Plug in solution below
else
% Optimization options
options = optimset('Algorithm','interior-point','Display','iter','MaxIter',500,'OutputFcn',#outfun);
% Optimize objective
objective = #(L) -L;
xsol = fmincon(objective,IC,[],[],[],[],LB,UB,confun,options);
% Known optimized solution from IMSL library
% a = 0.799266;
% lim = pi/2;
disp(['IMSL coeff (a): 0.799266 Upper bound (L): ',num2str(pi/2)])
disp(['code coeff (a): ',num2str(history.a(end)),' Upper bound: ',num2str(xsol)])
end
% http://stackoverflow.com/questions/7921133/anonymous-functions-calling-functions-with-multiple-output-forms
function varargout = get_outputs(fn, ixsOutputs)
output_cell = cell(1,max(ixsOutputs));
[output_cell{:}] = (fn());
varargout = output_cell(ixsOutputs);
end
function stop = outfun(x,optimValues,state)
stop = false;
switch state
case 'init'
case 'iter'
% Concatenate current point and objective function
% value with history. x must be a row vector.
history.fval = [history.fval; optimValues.fval];
history.x = [history.x; x(1)];
history.a = [history.a; a_of_L(x(1))];
case 'done'
otherwise
end
end
end
I could really use some help setting up the constrained optimization. I'm not only new to optimizations, I've never used MATLAB to do so. I should also note that what I have above does not work and is incorrect for the constrained optimization.
UPDATE: I added a for loop in the section if optimizeto show what I'm trying to achieve with the optimization. Obviously, I could just use this, but it seems very inefficient, especially if I increase the resolution of range and have to run this optimization many times. If you uncomment the plots, it will show how the bandwidth behaves. By looping over the full range, I'm basically testing every L but surely there's got to be a more efficient way to do this??
UPDATE: Solved
So it seems fmincon is not the only tool for this job. In fact I couldn't even get it to work. Below, fmincon gets "stuck" on the IC and refuses to do anything...why...that's for a different post! Using the same layout and formulation, fminbnd finds the correct solution. The only difference, as far as I know, is that the former was using a conditional. But my conditional is nothing fancy, and really unneeded. So it's got to have something to do with the algorithm. I guess that's what you get when using a "black box". Anyway, after a long, drawn out, painful, learning experience, here is a solution:
options = optimset('Display','iter','MaxIter',500,'OutputFcn',#outfun);
% Conditional
index = #(L) min(find(abs([dpdx(range(range<=L),a_of_L(L)),inf] - 1) - tol > 0,1,'first'),length(range));
% Optimize
%xsol = fmincon(#(L) -range(index(L)),IC,[],[],[],[],LB,UB,confun,options);
xsol = fminbnd(#(L) -range(index(L)),LB,UB,options);
I would like to especially thank #AndrasDeak for all their support. I wouldn't have figured it out without the assistance!
I'm using a simple if loop to change my parameter values within my ode script. Here is an example script I wrote that exhibits the same problem. So first the version which works:
function aah = al(t,x)
if (t>10000 && t<10300)
ab = [0; 150];
else
ab = [150; 0];
end
aah = [ab];
this can be run using
t = [0:1:10400];
x0 = [0,0];
[t,x] = ode23tb(#al, t,x0);
and visualised with
plot(t,x(:,1))
plot(t,x(:,2))
Ok that's the good version. Now if all you do is change t to
t = [0:1:12000];
the whole thing blows up. You might think it's just matlab averaging out the graph but it's not because if you look at
x(10300,2)
the answer should be the same in both cases because the code hasn't changed. but this second version outputs 0, which is wrong!
What on earth is going on? Anyone got an idea?
Thank you so much for any help
Your function is constant (except 10000 < t < 10300), and therefore the internal solver starts to solve the system with very large time step, 10% of total time by default. (In the adaptive ODE solver, if the system is constant, higher order and lower order solution will give the same solution, and the (estimated) error will be zero. So the solver assumes that current time step is good enough.) You can see if you give tspan with just two element, start and end time.
t = [0 12000];
Usually the tspan does not affect to the internal time step of solver. The solvers solve the system with their internal time step, and then just interpolate at tspan given by the user. So if the internal time step unfortunately "leap over" the interval [10000, 10300], the solver won't know about the interval.
So you better set the maximum step size, relatively smaller than 300.
options = odeset('MaxStep', 10);
[t, x] = ode23tb(#al, t, x0, options);
If you don't want to solve with small step size whole time (and if you "know" when the function are not constant), you should solve separately.
t1 = [0 9990];
t2 = [9990 10310];
t3 = [10310 12000];
[T1, x1] = ode23tb(#al, t1, x0);
[T2, x2] = ode23tb(#al, t2, x1(end,:));
[T3, x3] = ode23tb(#al, t3, x2(end,:));
T = [T1; T2(2:end); T3(2:end)];
x = [x1; x2(2:end,:); x3(2:end,:)];