I'm getting the error "Error using fmincon (line 300) A must have 'n' column(s)." when trying to solve the following optimisation code. I think there is an error in the definition of the constraints. Someone had the same problem http://goo.gl/35MeC but unfortunately I don't read chinese!!
The objective is to find the optimal values of the array Y subject to constraints on Y and on its integral IntY. To understand better the nature of the problem, each value of Y represent the value of a variable in a successive time step, and the objective function to minimise is basically a cost of interactions.
function [Y, IntY] = optTest()
% inputs of the problem
TS = 10; % number of time steps
YMin = -0.1; % minimum value of Y
YMax = 0.2; % maximum value of Y
IntYMin = 0.1; % min value of the integral of Y
IntYMax = 0.9; % max value of the integral of Y
IntYInit = 0.2; % initial value of the integral of Y
Prices = PricesFun(TS);
% use of function 'fmincon', preparation of the inputs
% x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub)
A = [tril(ones(TS))*1;tril(ones(TS))*-1];
b = [ones(TS,1)*(IntYInit-IntYMin);ones(TS,1)*(IntYMax-IntYInit)];
lb = ones(TS,1)*YMax;
ub = ones(TS,1)*YMin;
Y0 = ones(TS)*IntYInit;
Y = fmincon(#(x) costFun(x, Prices),Y0,A,b,[],[],lb,ub);
IntY = cumsum(Y);
function cost = costFun(x, Prices)
cost = sum(x*Prices);
function P = PricesFun(TS)
x = linspace(1,TS,TS);
pi = 3.1415;
P = 2 + sin(x/TS*4*pi);
The code above is self contained, if you want to try, you have just to paste it in matlab and call the function:
[Y, IntY] = optTest();
Your initial guess Y0 is what defines the number of variables involved in the optimization. You are inputting a TS x TS square matrix for Y0, which would require TS*TS linear constraints. Given that you're using column vectors for lb and ub, I assume you meant to create Y0 as a column vector as well, or Y0 = ones(TS,1)*IntYInit;
Related
I am trying to find log Maximum likelihood estimation for Gaussian distribution, in order to estimate parameters.
I know that Matlab has a built-in function that does this by fitting a Gaussian distribution, but I need to do this with logMLE in order to expand this method later for other distributions.
So here is the log-likelihood function for gaussian dist :
Gaussian Log MLE
And I used this code to estimate the parameters for a set of variables (r) with fminsearch. but my search does not coverage and I don't fully understand where is the problem:
clear
clc
close all
%make random numbers with gaussian dist
r=[2.39587291079469
1.57478022109723
-0.442284350603745
4.39661178526569
7.94034385633171
7.52208574723178
5.80673144943155
-3.11338531920164
6.64267230284774
-2.02996003947964];
% mu=2 sigma=3
%introduce f
f=#(x,r)-(sum((-0.5.*log(2*3.14.*(x(2))))-(((r-(x(2))).^2)./(2.*(x(1))))))
fun = #(x)f(x,r);
% starting point
x0 = [0,0];
[y,fval,exitflag,output] = fminsearch(fun,x0)
f =
#(x,r)-(sum((-0.5.*log(2*3.14.*(x(2))))-(((r-(x(2))).^2)./(2.*(x(1))))))
Exiting: Maximum number of function evaluations has been exceeded
- increase MaxFunEvals option.
Current function value: 477814.233176
y = 1×2
1.0e+-3 *
0.2501 -0.0000
fval = 4.7781e+05 + 1.5708e+01i
exitflag = 0
output =
iterations: 183
funcCount: 400
algorithm: 'Nelder-Mead simplex direct search'
message: 'Exiting: Maximum number of function evaluations has been exceeded↵ - increase MaxFunEvals option.↵ Current function value: 477814.233176 ↵'
Rewrite f as follows:
function y = g(x, r)
n = length(r);
log_part = 0.5.*n.*log(x(2).^2);
sum_part = ((sum(r-x(1))).^2)./(2.*x(2).^2);
y = log_part + sum_part;
end
Use fmincon instead of fminsearch because standard deviation is
always a positif number.
Set standard deviation lower bound to zero 0
The entire code is as follows:
%make random numbers with gaussian dist
r=[2.39587291079469
1.57478022109723
-0.442284350603745
4.39661178526569
7.94034385633171
7.52208574723178
5.80673144943155
-3.11338531920164
6.64267230284774
-2.02996003947964];
% mu=2 sigma=3
fun = #(x)g(x, r);
% starting point
x0 = [0,0];
% borns
lb = [-inf, 0];
ub = [inf, inf];
[y, fval] = fmincon(fun,x0,[],[],[],[],lb,ub, []);
function y = g(x, r)
n = length(r);
log_part = 0.5.*n.*log(x(2).^2);
sum_part = ((sum(r-x(1))).^2)./(2.*x(2).^2);
y = log_part + sum_part;
end
Solution
y = [3.0693 0.0000]
For better estimation use mle() directly
The code is quiet simple:
y = mle(r,'distribution','normal')
Solution
y = [3.0693 3.8056]
Question: Find the minimum of f(x,y)=x^2+y^2-2*x-6*y+14 in the window [0,2]×[2,4] with increment 0.01 for x and y.
My approach: Find the first partial derivatives fx and fy. The critical points satisfy the equations fx(x,y) = 0 and fy(x,y) = 0 simultaneously. find the second order partial derivatives fxx(x,y), fyy(x,y) and fxy(x,y) in order to find D.
clc
clear all
syms x y
fun=x^2+y^2-2*x-6*y+14;
fx=diff(fun,x);
fy=diff(fun,y);
pt=solve(fx==0,fy==0);
sol = struct2array(pt)
fxx=diff(fx,x);
fyy=diff(fy,y);
fxy=diff(fx,y);
D=subs(fxx,[x y],[1 3])*subs(fyy,[x y],[1 3])-(subs(fxy,[x y],[1 3]))^2
fxx_val=subs(fxx,[x y],[1 3])
minimum_value=subs(fun,[x y],[1 3])
Am I doing the right thing about what the question asked? Besides what about the window and increment mentioned that question. Any hints or solution will be appreciated .
Thanks in advance .
Use function evaluation optimization method instead of gradient
Please read through the code
f = #(x,y)x.^2+y.^2-2.*x-6.*y+14;
% x range
x_lb = 0;
x_ub = 2;
% y range
y_lb = 2;
y_ub = 4;
step = 0.01;
% lower bound of x, initial guess as xmin
xmin = x_lb;
% lower bound of y, initial guess as ymin
ymin = y_lb;
% f at the lower bounds, initial fmin
fmin = f(xmin, ymin);
for x = x_lb:step:x_ub
for y = y_lb:step:y_ub
% function evaluation
fval = f(x, y);
%replace fmin if the newly evaluated f is less than the actual fmin
if fval < fmin
fmin = fval;
% save current x and y where f is minimum
xmin = x;
ymin = y;
end
end
end
Solution
xmin = 1;
ymin = 3;
fmin = 4;
I would suggest to make use of Matlab's capabilities to compute with matrices. Then, no loop is required.
% your function, look up anonymous functions
func = #(x,y) x.^2 + y.^2 - 2.*x - 6.*y + 14;
% get matrices for you x- and y-window
[xg, yg] = meshgrid(0:.01:2, 2:0.01:4);
% compute all in one call
result = func(xg,yg);
% find total minimum
minimum = min(result(:));
% find the index of the (first) minimum, for other equations, there might
% be more than one
ind = find(result==minimum, 1);
% Output the result
fprintf('The minimum (%d) is located at x: %d, y: %d.\n', minimum, xg(ind), yg(ind));
In the integral
I want to optimize the function Dt, as I know the end result of the integral. I have expressions for k1 and k0 in terms of k2 and N, and it is k2 and N that I would like to optimize. They have constraints, needing to be between certain values. I have it all setup in my code, but I am just unaware of how to tell the genetic alogrithm to optimize an integral function? Is there something I'm missing here? The integral is usually evaluated numerically but I am trying to go backwards, and assuming I know an answer find the input parameters
EDIT:
All right, so here's my code. I know the integral MUST add up to a known value, and I know the value, so I need to optimize the variables with that given parameter. I have created an objective function y= integral - DT. I kept theta as syms because it is the thing being integrated to give DT.
function y = objective(k)
% Define constants
AU = astroConstants(2);
mu = astroConstants(4);
% Define start and finish parameters for the exponential sinusoid.
r1 = AU; % Initial radius
psi = pi/2; % Final polar angle of Mars/finish transfer
phi = pi/2;
r2 = 1.5*AU;
global k1
k1 = sqrt( ( (log(r1/r2) + sin(k(1)*(psi + 2*pi*k(2)))*tan(0)/k(1)) / (1-
cos(k(1)*(psi+2*pi*k(2)))) )^2 + tan(0)^2/k(1)^2 );
k0 = r1/exp(k1*sin(phi));
syms theta
R = k0*exp(k1*sin(k(1)*theta + phi));
syms theta
theta_dot = sqrt((mu/(R^3))*1/((tan(0))^2 + k1*(k(1))^2*sin(k(1)*theta +
phi) + 1));
z = 1/theta_dot;
y = int(z, theta, 0,(psi+2*pi*k(2))) - 1.3069e08;
global x
x=y;
end
my k's are constrained, and the following is the constraint function. I'm hoping what I have done here is tell it that the function MUST = 0.
function [c,c_eq] = myconstraints(k)
global k1 x
c = [norm(k1*(k(1)^2))-1 -norm(k1*(k(1)^2))];
c_eq =[x];
end
And finally, my ga code looks like this. Honestly, I've been playing with it all night and getting error messages after error messages - ranging from "constraint function must return real value" to "error in fcnvectorizer" and "unable to convert expression into double array", with the last two coming after i've removed the constraints.
clc; clear;
ObjFcn = #objective;
nvars = 2
LB = [0 2];
UB = [1 7];
ConsFcn = #myconstraints;
[k,fval] = ga(ObjFcn,nvars,[],[],[],[],LB,UB,ConsFcn);
I've been stuck on this problem for weeks and have gotten nowhere, even with searching through literature.
The documentation online for this particular function is poor, and I was looking for an example on how to use it. It seems to take in 9+ arguments, but I'm not entirely sure what they even are. I am working on implementing function using the trapezoidal rule, however, I am missing the functions that compute the partial derivatives with respect to y and t. I believe that calculating one for t in MATLAB is another case, but here, I'm just trying to use MATLAB to compute it for y.
I'm using the following input initially:
func = #(t,y)(y.^2+y+t);
interval = [0 1];
y0 = 0;
[steps, derivY, derivJ, W, inverseW] = getTrapezoidalODEValues(func, interval, y0)
I set up the function like this:
function [h,J,T,W,iW] = getTrapezoidalODEValues(odefun,tspan,y0,options)
if (nargin==3)
options = odeset();
end
h = NaN; J(0) = NaN; T(0) = NaN; W(0) = NaN; iW = NaN;
[t,yy] = ode(odefun,tspan,y0,options);
[nstep,ndim] = size(yy);
d = 1/(2+sqrt(2));
for j=2:nsteps
h = t(j)-t(j-1);
I = eye(???,???); % identity matrix
quadpoly = ???; % the quadratic polynomial
J(j-1) = numjac(???); % <--partial derivative of odefun with respect to y
T(j-1) = ???; % partial derivative of odefun with respect to t
W(j-1) = I - h .* d .* J;
iW(j-1) = inv(W(j-1));
end
end
I have some obscurely long symbolic expression of 3 variables (g_eq), which i would like to minimize with some constraints. I am trying to do so by converting it to a function handle and using fmicon:
cfun = matlabFunction(g_eq,'vars',[kappa;theta;sigma]);
A = [-1 0 0; 0 -1 0; 0 0 -1];
b = [0; 0; 0];
[x,fval] = fmincon(#(kappa, theta, sigma) cfun, x0, A, b)
Which Matlab doesn't like:
FMINCON requires all values returned by user functions to be of
data type double.
I would suspect, that the problem is with cfun, as it is full of numbers with symbolic precision, can I somehow convert it, so that they're double? Or better (computation time wise) while creating my objective function (cfun) (complicated process of some transformation of data and a parametric model), can I use symbols or some other "proxy for the variables" with double for the numeric part of the expressions?
Thanks,
J.
Edit - MCVE:
My aim is to find parameters of a model by minimizing a difference between the model implied and data implied laplace transforms over some weighted regions. Here I provide the problem over one small region without use of weights over the regions and some further simplifications. In part 0, I provide the code for functions of the transformation, in part II I make the parametric transformation, while in III the data transformation and attempt to minimize it in IV.
%% 0. Functions used
%% 0.1 L_V1 - transform of parametric
function lv = L_V1(u,sigma,kappa,theta)
lv = (1/(1+u.*sigma^2/(2*kappa))).^(2*kappa*theta/sigma^2);
end
%% 0.2 LV_2 - transform of data
function lv = L_hat1(u,D,n,T)
A_u = cos(sqrt(2 .*u) *sqrt(n) .*D);
Z_u = 1/n * sum(A_u);
lv = 1/T * sum(Z_u);
end
%% I. Pre-estimation
ulng1=100; %select number of points on the evaluated interval
u1 = linspace(.8, 1.6,ulng1); % create region of interest
%% II. Parametric part
par_mat1 = sym(zeros(ulng1,1)); % create interval for parametric
syms sigma kappa theta LV_par1;
for i = 1:ulng1
par_mat1(i) = L_V1(u1(i),sigma,kappa,theta); %transformations of parametric
end
LV_par1 = sum(par_mat1); %sum of parametric over the region
%% III. Data part
n = 100; %choose number of days
T = 20; %choose number of obs over a day
D = rand([n-1, T]); %vector of observations, here just random numbers
for i = 1:ulng1
hat_mat1(i) = L_hat1(u1(i),D,n,T); %transformations of data
end
hat_1 = sum(hat_mat1); %sum of transforms over the region
%% IV. Minimize
W = 1; %weighting matrix, here just one region, hence 1
MC = hat_1 - LV_par1 ; %moment condition
g_eq = (MC) * (W) *(MC.'); %objective function (symbolic)
cfun = matlabFunction(g_eq,'vars',[kappa;theta;sigma]); %create a function handle from the symbolic
x0 = [.5; 1; .5];
A = [-1 0 0; 0 -1 0; 0 0 -1]; %constrains
b = [0; 0; 0]; %constrains
[x,fval] = fmincon(#(kappa, theta, sigma) cfun, x0, A, b) %minimize
The optimization parameters are always passed as vector.
[x,fval] = fmincon(#(x) cfun(x(1),x(2),x(3)), x0, A, b)