Maximization under non-linear constraints in MATLAB using fmincon - matlab

I am trying to solve maximize a function s.t. 14 constraints and with 15 variables.
Some of them are linear, some are not. They are all equations (no inequalities).
I have tries using 'fsolve' and 'solve', using lagrange (ended up with 29 equations and 30 variables) - that didn't go that well...
I moved on to fmincon. I've set a script with an objective function in a file named objectfun.m:
function f = objectfun(x,I,rho)
% SWAPPING VARIABLE NAMES FOR READABILITY:
w = x(1);
t = x(2);
beta = x(3);
r = x(4);
% VALUE FUNCTION TO BE MINIMIZES:
f = -(rho*w*(1-t)+beta+I*(1+(1-t)*r));
I have set another one with the constraints:
function [c, ceq] = confun(x,...
Bs,Bu,sigma_s,sigma_u,rho,c_bar,I,A,alpha)
% SWAPPING VARIABLE NAMES FOR READABILITY:
w = x(1);
t = x(2);
beta = x(3);
r = x(4);
vum = x(5);
vsm = x(6);
ms = x(7);
cstar = x(8);
zs = x(9);
zu = x(10);
H = x(11);
K = x(12);
Y = x(13);
L = x(14);
mu = x(15);
% INEQUILITY CONSTRAINTS:
c = [];
% EQUALITY CONSTRAINTS:
ceq = [ms-Bs*vsm^sigma_s; % 1
mu-Bu*vum^sigma_u; % 2
(1+r*(1-t))*cstar-(1-rho)*w*(1-t); % 3
zs-cstar/c_bar; % 4
zu-1+zs; % 5
H-(cstar^2)/(2*c_bar); % 6
I-K-H; % 7
A*(K^alpha)*(L^(1-alpha))-Y; % 8
L-(zs+rho*zu+ms+rho*mu); % 9
w-(1-alpha)*A*(K/L)^alpha; % 10
r-alpha*A*(K/L)^(alpha-1); % 11
t*Y-beta*(1+ms+mu); % 12
vum-rho*w*(1-t)-beta; % 13
vsm-w*(1-t)-beta]; % 14
And a main script:
%% Parameters:
Bs =0.0;
Bu =0.0;
sigma_s = 1.5;
sigma_u = 1.5;
rho = 0.33;
c_bar = 6;
I = 3;
A = 1;
alpha = 0.33;
%% Numeric Solution:
x0 = 0.5*ones(length(var_names),1);
objective = #(x)objectfun(x,I,rho);
constraints = #(x)confun(x,...
Bs,Bu,sigma_s,sigma_u,rho,c_bar,I,A,alpha);
options = optimoptions(#fmincon);
[s,fval] = fmincon(objective,x0,[],[],[],[],[],[],constraints,options);
The question:
The solution is nonsense. I went over the equations many times - let's assume their good! (please...[= )
Did I choose the right application for my problem (fmincon)?
Is there a problem with the structure or in the code specifically?
Do you have any suggestions on how to make my life a bit easier?
I plan on iterating on the solution using different parameter values. Is there any way of verifying the solution, for a given set, just to see if the solution is correct?
Thanks in advance!!!

Here are some things you can do:
Provide reasonable bounds on all variables. This will prevent the solver to go to areas where things do not make sense, and where the functions (and gradients) can not be evaluated.
Provide a better starting point.
Provide gradients. Unless you have a system that can do automatic differentiation it is often important to provide correct and exact gradients. (Some solvers may also require second derivatives).
If you have a known solution for a given data set, pass this on as initial point and see what happens. Further you can fix this solution by setting lower and upper-bounds equal to this known solution and then see what happens then.
Try a more powerful modeling system/solver. E.g. GAMS with CONOPT is often used in economic modeling and provides automatic differentiation and gives often better feedback if something goes wrong. This is a small problem so you should be able to run it with the free student/demo version (http://gams.com/download/). The other suggestions can be applied here also.

Related

Is there any way to define a variable from a formula depending on what variables are given?

Imagine you have the following formula:
a=4*b*c^2
Is there any way in Matlab to program this is in a way that the if 2 of 3 variables are provided, Matlab will solve and provide the missing one?
Because the only alternative I am seeing is using switch-case and solving the equation myself.
if isempty(a)
switchVar=1
elseif isempty(b)
switchVar=2;
else
switchVar=3;
end
switch switchVar
case 1
a=4*b*c^2;
case 2
b=a/4/c^2;
case 3
c=sqrt(a/4/b);
end
Thanky you very much in advance!
For a numeric (rather than symbolic) solution...
You can do this with some faffing around and anonymous functions. See the comments for details:
% For the target function: 0 = 4*b*c - a
% Let x = [a,b,c]
% Define the values we know about, i.e. not "c"
% You could put any values in for the known variables, and NaN for the unknown.
x0 = [5, 10, NaN];
% Define an index for the unknown, and then clear any NaNs
idx = isnan(x0);
x0(idx) = 0;
% Make sure we have 1 unknown
assert( nnz( idx ) == 1 );
% Define a function which handles which elements of "x"
% actually influence the equation
X = #(x,ii) ( x*idx(ii) + x0(ii)*(~idx(ii)) );
% Define the function to solve, 0 = 4*b*c - a = 4*x(2)*x(3)^2 - x(1) = ...
f = #(x) 4 * X(x,2) * X(x,3).^2 - X(x,1);
% Solve using fzero. Note this requires an initial guess
x0(idx) = fzero( f, 1 );
We can check these results are correct by plotting the function for a range of c values, and checking the intersection with the x-axis aligns to the output x0(3):
c = -1:0.01:1;
y = 4*x(2)*c.^2-x(1);
figure
hold on
plot(t,y);
plot(t,y.*0,'r');
plot(x0(3),0,'ok','markersize',10,'linewidth',2)
Note that there were 2 valid solutions, since this is a quadratic. The initial condition provided to fzero will largely dictate which solution is found.
Edit:
You can condense this down a bit with some tweaks to my earlier syntax:
% Define all initial conditions. This includes known variable values
% i.e. a = 5, b = 10
% As well as the initial guess for unknown variable values
% i.e. c = 1 (maybe? ish?)
x0 = [5, 10, 1];
% Specify the index of the unknown variable in x
idx = 3;
% Define the helper function which handles the influence of each variable
X = #(x,ii) x*(ii==idx) + x0(ii)*(ii~=idx);
% Define the function to solve, as before
f = #(x) 4 * X(x,2) * X(x,3).^2 - X(x,1);
% Solve
x0(idx) = fzero( f, x0(idx) )
This approach has the benefit that you can just change idx (and re-run the definition steps for X and f) to switch the variable of choice!
First, specify the given known variables
Then rewrite the equation as 0 = 4*b*c - a
Finally use solve to find the missing value
Code is as follows
syms a b c
% define known variable
a = 2; c = 5;
% equation rewritten
f = 4*b*c^2 - a == 0;
missing_value = solve(f);

Trying to minimise a function wrt 2 variables for robust portfolio optimisation. How to do this with fmincon?

I am currently involved in a group project where we have to conduct portfolio selection and optimisation. The paper being referenced is given here: (specifically page 5 and 6, equations 7-10)
http://faculty.london.edu/avmiguel/DeMiguel-Nogales-OR.pdf
We are having trouble creating the optimisation problem using M-Portfolios, given below
min (wrt w,m) (1/T) * sum_(rho)*(w'*r_t - m) (Sorry I couldn't get the formatting to work)
s.t. w'e = 1 (just a condition saying that all weights add to 1)
So far, this is what we have attempted:
function optPortfolio = portfoliofminconM(returns,theta)
% Compute the inputs of the mean-variance model
mu = mean(returns)';
sigma = cov(returns);
% Inputs for the fmincon function
T = 120;
n = length(mu);
w = theta(1:n);
m = theta((n+1):(2*n));
c = 0.01*ones(1,n);
Aeq = ones(1,(2*n));
beq = 1;
lb = zeros(2,n);
ub = ones(2,n);
x0 = ones(n,2) / n; % Start with the equally-weighted portfolio
options = optimset('Algorithm', 'interior-point', ...
'MaxIter', 1E10, 'MaxFunEvals', 1E10);
% Nested function which is used as the objective function
function objValue = objfunction(w,m)
cRp = (w'*(returns - (ones(T,1)*m'))';
objValue = 0;
for i = 1:T
if abs(cRp(i)) <= c;
objValue = objValue + (((cRp(i))^2)/2);
else
objValue = objValue + (c*(abs(cRp(i))-(c/2)));
end
end
The problem starts at our definitions for theta being used as a vector of w and m. We don't know how to use fmincon with 2 variables in the objective function properly. In addition, the value of the objective function is conditional on another value (as shown in the paper) and this needs to be done over a rolling time window of 120 months for a total period of 264 months.(hence the for-loop and if-else)
If any more information is required, I will gladly provide it!
If you can additionally provide an example that deals with a similar problem, can you please link us to it.
Thank you in advance.
The way you minimize a function of two scalars with fmincon is to write your objective function as a function of a single, two-dimensional vector. For example, you would write f(x,y) = x.^2 + 2*x*y + y.^2 as f(x) = x(1)^2 + 2*x(1)*x(2) + x(2)^2.
More generally, you would write a function of two vectors as a function of a single, large vector. In your case, you could rewrite your objfunction or do a quick hack like:
objfunction_for_fmincon = #(x) objfunction(x(1:n), x(n+1:2*n));

Create function to use in ode45

So this is part of a larger project but I am stuck on number two of this section. I rewrote the system to get it in the required form:
dx(1)/dt = x(2)
dx(2)/dt = (-(M+m)/mL))x(4) + 1/(mL)u
dx(3)/dt = x(4)
dx(4)/dt = -(mg/M)x(1) + (1/M)u
After substituting the variables given in the problem I wrote the funcion:
function dx = fun(t,x)
dx = zeros(4,1);
dx(1) = x(2);
dx(2) = -((2+.1)/(.1*.5)).*x(4);
dx(3) = x(4);
dx(4) = -((.1*9.81)/2).*x(1);
end
I am confused on how to implement u(t) = 0 and how to create the theta function.
Any help even if its just pointing me in the right direction would be amazing. Thank you in advance :)
It's easy. You implement theta as another state. This is possible since you know the derivative, which does not even depend on the other states. To be more precise, you should add two more states here. One for theta and one for theta_dot.
dx(5) = x(6) % Theta'
dx(6) = -0.1 % Theta''
And by the way, you can also pass additional variables to your differential equation. You just add more arguments to it
function dx = diffeq(t,x,parameters)
...
end
and create a new function handle where you execute the ODE solver
[T,X] = ode45(#(t,x)diffeq(t,x,parameters),t_span,X0, ode_options);
This is just a hint since you're using magic numbers in your differential equation function.

Simulations hang when running ode45

I'm suppose to make a model for an algae population. Here's the code I have so far (all written from examples online). When i run Solve_algaepop, it just hangs for a long time.
Any ideas why? Is there any obvious thing I'm doing wrong? The equations are from a research paper.
This is Solve_algaepop.m. In the equations for r1 and r2, P10 and P20 are supposed to be the values
P1 = x(1) and P2 = x(2) defined in algaepop_model.m. I don't know how to access the values when I'm in Solve_algaepop.m
% Initial conditions
P10 = 560000; %from Chattopadhyay; estimated from graph
P20 = 250000; %same as above
Z0 = 280000; %
N0 = 0.6; %from Edwards
%some variables that the expressions of the parameters use
lambda = .6;
mu = .035;
k = 0.05;
%define parameters (start with estimates from Edwards paper):
r1 = (N0/(.03+N0))*((.2*P10)/(.2 + .4*P10));
r2 = (N0/(.03+N0))*((.2*P20)/(.2 + .4*P20));
a = Z0*((lambda*P10^2)/(mu^2 + P10^2));%G1: zooplankton growth function from Edwards paper
% m1 = .15; %r in Edwards paper
m1 = .075; % q in Edwards
m2 = .15;% r in Edwards paper
m3 = .15; % r in Edwards paper
d = 0.5;
cN = k;%*(N-N0);
par = [r1 r2 a m1 m2 m3 d cN]; % Creates vector of parameter values to pass to the ode solver
tspan = 0:1:300; %(Note: can also use the function linspace)
x0 = [P10 P20 Z0 N0]; % Creates vector of initial conditions
[t,x] = ode45(#algaepop_model,tspan,x0,[],par);
plot(t,x)
And here is algaepop_model.m
function dxdt = algaepop_model(t,x,par)
P1 = x(1);
P2 = x(2);
Z = x(3);
N = x(4);
r1 = par(1);
r2 = par(2);
a = par(3);
m1 = par(4);
m2 = par(5);
m3 = par(6);
d = par(7);
cN = par(8);
dxdt = zeros(4,1);
dxdt(1) = r1*N*P1 - m3*P1 - a*P1*Z;
dxdt(2) = r2*N*P2 - a*P2*Z - m2*P2;
dxdt(3) = a*P2*Z + a*P1*Z - m1*Z;
dxdt(4) = d*m2*P2 + d*m1*Z + d*m3*P1 + cN - r2*N*P2 - r1*N*P1;
end
Thanks for the help.
Let's debug. One of the simplest things that you can do is print out t and x inside of your integration function, algaepop_model. As soon as you do this, you'll probably notice what's happening: ode45 is taking extremely small steps. They're on the order of 1.9e-9. With steps that small, it will take forever to simulate to t = 300 (and even longer if you print stuff out on each step).
This might be caused by a poor choice of initial conditions, poor scaling or dimensionalization, a typo resulting in the wrong equations, or simply that you're using an inappropriate solver (and/or tolerances) for the particular problem. I can't really address the first two situations and must assume that you don't have any errors. Thus, in this case you have what is effectively a stiff system and ode45 is not a particularly good choice in such cases. Simply changing the solver to ode15s results in the following plot almost immediately:
As you can see, there are very large changes over a short period of time in the initial portion of the plot. If you zoom in you'' see that the huge spike happens in the first unit of time (you might output more time points or just let tspan = [0 300]). Some state variables are changing rapidly while others are varying more gradually. Such high frequencies and differences in time scales are the hallmarks of stiff systems. I'd suggest that, in addition to confirming that your code is correct, you also try adjusting the integration tolerances as well via odeset. Make sure that tighter tolerances produce qualitatively similar results. You can also try the other stiff solvers in the ODE suite if you like.
Lastly, it's more efficient and up-to-date to pass your parameters via the function handle itself rather than how you're doing it. Here's how:
[t,x] = ode15s(#(t,x)algaepop_model(t,x,par),tspan,x0);

Need help plotting this function in Matlab

I recently started using Matlab and I am trying to plot Imaginary part of a function. I can see I am making a mistake somewhere because I have the graph showing what I need to get and I am getting something else. Here is the link of the graph that I need to get, that I am getting and a function that I am plotting:
I know that this function has a singularity at frequency around 270 Hz and I don't know if a 'quadgk' can solve integral then. You guys probably know but theta function inside the integral is a heaviside and I don't know if that is causing problem maybe? Is there something wrong I am doing here? Here is the matlab code I wrote:
clear all
clc
ff=1:10:1000;
K1=(2*3)*log(2*cosh(135/6))/pi;
theta1=ones(size(ff));
theta1(ff<270)=0;
I1=zeros(size(ff));
for n = 1:numel(ff)
f = ff(n);
I1(n)= K1/f + (f/pi)*quadgk(#(x)(sinh(x/3)/(cosh(135/3)+cosh(x/3))-theta1(n))./((f^2)-4*(x.^2)), 0, inf);
end
plot(ff,I1, 'b');
hold on
axis([0 1000 -0.3 1])
First, I altered the expression for your heaviside function to what I think is the correct form.
Second, I introduced the definitions of mu and T explicitly.
Third, I broke down the integral into 4 components, as follows, and evaluated them individually (along the lines of what Fraukje proposed)
Fourth, I use quadl, although this is prob. of minor importance.
(edit) Changed the range of ff
Here's the code with changes:
fstep=1;
ff=[1:fstep:265 275:fstep:1000];
T = 3;
mu = 135;
df = 0.01;
xmax = 10;
K1=(2*T/pi)*log(2*cosh(mu/(2*T)));
theta1=ones(size(ff));
theta1(ff-2*mu<0)=0;
I1=zeros(size(ff));
for n = 1:numel(ff)
f = ff(n);
sigm1 = #(x) sinh(x/T)./((f^2-4*x.^2).*(cosh(mu/T)+cosh(x/T)));
sigm2 = #(x) -theta1(n)./(f^2-4*x.^2);
I1(n) = K1/f + (f/pi)*quadl(sigm1,0,f/2-df); % term #1
% I1(n) = I1(n) + (f/pi)*quadl(sigm1,f/2+df,xmax); % term #2
% I1(n) = I1(n) + (f/pi)*quadl(sigm2,0,f/2-df); % term #3
% I1(n) = I1(n) + (f/pi)*quadl(sigm2,f/2+df,xmax); % term #4
end
I selected to split the integrals around x=f/2 since there is clearly a singularity there (division by 0). But additional problems occur for terms #2 and #4, that is when the integrals are evaluated for x>f/2, presumably due to all of the trigonometric terms.
If you keep only terms 1 and 3 you get something reasonably similar to the plot you show:
However you should probably inspect your function more closely and see what can be done to evaluate the integrals for x>f/2.
EDIT
I inspected the code again and redefined the auxiliary integrals:
I1=zeros(size(ff));
I2=zeros(size(ff));
I3=zeros(size(ff));
for n = 1:numel(ff)
f = ff(n);
sigm3 = #(x) sinh(x/T)./((f^2-4*x.^2).*(cosh(mu/T)+cosh(x/T))) -theta1(n)./(f^2-4*x.^2);
I1(n) = K1/f + (f/pi)*quadl(sigm3,0,f/2-df);
I2(n) = (f/pi)*quadl(sigm3,f/2+df,10);
end
I3=I2;
I3(isnan(I3)) = 0;
I3 = I3 + I1;
This is how the output looks like now:
The green line is the integral of the function over 0<x<f/2 and seems ok. The red line is the integral over Inf>x>f/2 and clearly fails around f=270. The blue curve is the sum (the total integral) excluding the NaN contribution when integrating over Inf>x>f/2.
My conclusion is that there might be something wrong with the curve as you expect it to look.
So far I'd proceed this way:
clc,clear
T = 3;
mu = 135;
f = 1E-04:.1:1000;
theta = ones(size(f));
theta(f < 270)= 0;
integrative = zeros(size(f));
for ii = 1:numel(f)
ff = #(x) int_y(x, f(ii), theta(ii));
integrative(ii) = quad(ff,0,2000);
end
Imm = ((2*T)./(pi*f)).*log(2*cosh(mu/(2*T))) + (f/pi).*integrative;
Imm1 = exp(interp1(log(f(1:2399)),log(Imm(1:2399)),log(f(2400):.001:f(2700)),'linear','extrap'));
Imm2 = exp(interp1(log(f(2985:end)),log(Imm(2985:end)),log(f(2701):.001:f(2984)),'linear','extrap'));
plot([(f(2400):.001:f(2700)) (f(2701):.001:f(2984))],[Imm1 Imm2])
hold on
axis([0 1000 -1.0 1])
plot(f,Imm,'g')
grid on
hold off
with
function rrr = int_y(x,f,theta)
T = 3;
mu = 135;
rrr = ( (sinh(x./T)./(cosh(mu/T) + cosh(x/T))) - theta ) ./ (f.^2 - 4.*(x.^2));
end
I've come up with this plot: