How can I perform non-linear constrained optimization using fmincon over a range of values for the non-linear constraint?

I'm trying to minimize an objective function (portfolio risk) subject to a non-linear constraint (portfolio return) by finding optimal asset shares within the portfolio. At the moment I have been able to do so for a given level of return entered manually into the non-linear contraint function as a scalar. However, I would like to be able to calculate and store optimal asset shares over a range of levels of return without having to manually change them in the constraint function each time.
The objective function is:
function f = objecfun(x);
p=csvread('trialpolitical.csv');
f = p'*(x.*x);
end
The non-linear constraint (with a manually entered level of return 'g' of 0.0252):
function [c, ceq] = nonlconstr(x)
c = [];
r=csvread('trialreturns.csv');
g=0.0252;
ceq = [g-(ones(1,35)*(x.*r))];
end
The file I am running the optimization from is:
clear all
x0=csvread('x0.csv');
r=csvread('trialreturns.csv'); %asset returns
p=csvread('trialpolitical.csv'); %asset political risk
m=csvread('trialconstraints.csv'); %maximum asset shares
options = optimset;
% Modify options setting
options = optimset(options,'Display', 'off');
options = optimset(options,'Algorithm', 'interior-point');
A=[];
b=[];
Aeq=ones(1,35);
beq=1;
lb=zeros(35,1);
ub=m;
[x fval] = fmincon(@objecfun,x0,A,b,Aeq,beq,lb,ub,@nonlconstr);
Any help would be much appreciated!

Answers (1)

Rewrite your nonlinear constraint this way. By the way, these constraints look pretty linear to me
function [c, ceq] = nonlconstr(x,g,r)
c = [];
ceq = [g-(ones(1,35)*(x.*r))];
end
Then call fmincon as
i=0;
for g=range_of_g
i=i+1;
[x(i),fval(i)]=fmincon(@objecfun,x0,A,b,Aeq,beq,lb,ub,@(x)nonlconstr(x,r,g));
end
Except of course it's better to pre-allocate x(i) and fval(i).

3 Comments

This can only makes the objecfun satisfy the nonlconstr at discreet points, NOT all the range.
@Frank, if you don't like the answer, then you are completely free to post your own answer, insted of saying how bad this answer is. That is, if you know a better way to solve it, then show the better way. If you don't know how to solve the problem, then maybe your complaint is not appropriate?
@Frank It is not possible to store solutions for a continuum of g as the OP said he wished to do. A digital computer can only store a finite number of results. However, if you wanted to pursue a single solution x valid for an upper and lower bound on the portfolio return, it would be trivial to modify the proposed code:
function [c, ceq] = nonlconstr(x,gLower,gUpper, r)
ceq = [];
c(1) = [+gLower-(ones(1,35)*(x.*r))];
c(2) = [-gUpper+(ones(1,35)*(x.*r))];
end
As in 2012, though, I still think it would be better to write these as linear constraints, which the problem-based workflow will now do automatically for us,
x=optimvar('x',35,'Lower',0,'Upper',m);
y=sum(x.*r);
Constraints.con_sum=sum(x)<=1;
Constraints.con_gLower=y>=gLower;
Constraints.con_gUpper=y<=gUppper;
sol = solve( optimproblem( 'Objective',x.'*(x.*p),'Constraints',Constraints) )

Sign in to comment.

Categories

Asked:

on 6 Oct 2012

Edited:

on 10 May 2023

Community Treasure Hunt

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

Start Hunting!