I'm trying to solve a symbolic optimization problem using PSO optimizer in MATLAB. The variables r x a c n theta z are symbolic and CD is calculated by integrating r.
The CD is the objective function with free variables a,n, theta and lb and ub are bounds. Full code is as follows:
syms r x a c n theta z
assume(n,'positive');
D=0.24;
L=2;
f=L/D;
b=.8;
a0=0.02;
db=0.05;
V=1;
Re=(V*(D/2))/0.000001;
Cf=(0.075/(((log10(Re))-2)^2))+0.00025;
% Define r(x)
c=L-a-b-a0;
r1=0.5*D*(2*x/a)^(1/n);
I1=simplify(int(2*pi*r1,x,a0,a));
r2=D/2;
I2=simplify(int(2*pi*r2,x,a,a+b));
r3=(0.5*D)-((((3*D)/(2*(c)^2))-(tan(theta)/c))*(x-a-b)^2)+(((D/c^3 ...
(tand(theta)/c^2))*(x-a-b)^3);
I3=simplify(int(2*pi*r3,x,a+b,L));
A=simplify(I1+I2+I3);
Sn=pi*(D^2/4);
Cdstar=Cf*(1+(60*f^-3 )+(0.0025*f))*(A/(L^2));
Cdb=0.029*((db/D)^3)*(Cdstar^-0.5)*(Sn/(L^2));
CD=simplify(Cdstar+Cdb);
%optimization problem
objective=matlabFunction(CD,'Vars',[a,n,theta])
nVar=3;
lb = [deg2rad(5),0.25,a0];
ub = [deg2rad(60),5,L/2];
options =
optimoptions('particleswarm','SwarmSize',100,'HybridFcn',#fmincon);
[z,fval,exitflag,output] = particleswarm(objective,nVar,lb,ub,options)
And this is the error I get:
#(a,n,theta)pi.*4.404634153141517e-4+pi.*1.0./sqrt(pi.4.404634153141517e-4-pi.(a.*5.0-6.0).*1.0./(a.5.0e+1-5.9e+1).^3.(a.*2.32335e+6+tan((theta.*pi)./1.8e+2).*4.779e+6-tan(theta).*6.2658e+6-a.^2.*tan(theta).*2.655125e+7+a.^3.*tan(theta).*1.4875e+7-a.^4.*tan(theta).*3.125e+6-a.*tan((theta.*pi)./1.8e+2).*1.59975e+7+a.*tan(theta).*2.1063e+7+a.^2.*tan((theta.*pi)./1.8e+2).*2.008125e+7-a.^3.*tan((theta.*pi)./1.8e+2).*1.1203125e+7+a.^4.*tan((theta.*pi)./1.8e+2).*2.34375e+6-a.^2.*1.98e+6+a.^3.*5.625e+5-9.08811e+5).*1.223509486983755e-5-(n.pi.((a.*2.5e+1).^(-1.0./n)-2.0.^(1.0./n+1.0).*a.*2.5e+1).*1.101158538285379e-5)./(n+1.0)).9.440104166666668e-7-pi.(a.*5.0-6.0).*1.0./(a.5.0e+1-5.9e+1).^3.(a.*2.32335e+6+tan((theta.*pi)./1.8e+2).*4.779e+6-tan(theta).*6.2658e+6-a.^2.*tan(theta).*2.655125e+7+a.^3.*tan(theta).*1.4875e+7-a.^4.*tan(theta).*3.125e+6-a.*tan((theta.*pi)./1.8e+2).*1.59975e+7+a.*tan(theta).*2.1063e+7+a.^2.*tan((theta.*pi)./1.8e+2).*2.008125e+7-a.^3.*tan((theta.*pi)./1.8e+2).*1.1203125e+7+a.^4.*tan((theta.*pi)./1.8e+2).*2.34375e+6-a.^2.*1.98e+6+a.^3.*5.625e+5-9.08811e+5).*1.223509486983755e-5-(n.pi.((a.*2.5e+1).^(-1.0./n)-2.0.^(1.0./n+1.0).*a.*2.5e+1).*1.101158538285379e-5)./(n+1.0)
Not enough input arguments.
Error in
symengine>#(a,n,theta)pi.*4.404634153141517e-4+pi.*1.0./sqrt(pi.4.404634153141517e-4-pi.(a.*5.0-6.0).*1.0./(a.5.0e+1-5.9e+1).^3.(a.*2.32335e+6+tan((theta.*pi)./1.8e+2).*4.779e+6-tan(theta).*6.2658e+6-a.^2.*tan(theta).*2.655125e+7+a.^3.*tan(theta).*1.4875e+7-a.^4.*tan(theta).*3.125e+6-a.*tan((theta.*pi)./1.8e+2).*1.59975e+7+a.*tan(theta).*2.1063e+7+a.^2.*tan((theta.*pi)./1.8e+2).*2.008125e+7-a.^3.*tan((theta.*pi)./1.8e+2).*1.1203125e+7+a.^4.*tan((theta.*pi)./1.8e+2).*2.34375e+6-a.^2.*1.98e+6+a.^3.*5.625e+5-9.08811e+5).*1.223509486983755e-5-(n.pi.((a.*2.5e+1).^(-1.0./n)-2.0.^(1.0./n+1.0).*a.*2.5e+1).*1.101158538285379e-5)./(n+1.0)).9.440104166666668e-7-pi.(a.*5.0-6.0).*1.0./(a.5.0e+1-5.9e+1).^3.(a.*2.32335e+6+tan((theta.*pi)./1.8e+2).*4.779e+6-tan(theta).*6.2658e+6-a.^2.*tan(theta).*2.655125e+7+a.^3.*tan(theta).*1.4875e+7-a.^4.*tan(theta).*3.125e+6-a.*tan((theta.*pi)./1.8e+2).*1.59975e+7+a.*tan(theta).*2.1063e+7+a.^2.*tan((theta.*pi)./1.8e+2).*2.008125e+7-a.^3.*tan((theta.*pi)./1.8e+2).*1.1203125e+7+a.^4.*tan((theta.*pi)./1.8e+2).*2.34375e+6-a.^2.*1.98e+6+a.^3.*5.625e+5-9.08811e+5).*1.223509486983755e-5-(n.pi.((a.*2.5e+1).^(-1.0./n)-2.0.^(1.0./n+1.0).*a.*2.5e+1).*1.101158538285379e-5)./(n+1.0)
Error in particleswarm>makeState (line 694)
firstFval = objFcn(state.Positions(1,:));
Error in particleswarm>pswcore (line 169) state =
makeState(nvars,lbMatrix,ubMatrix,objFcn,options);
Error in particleswarm (line 151) [x,fval,exitFlag,output] =
pswcore(objFcn,nvars,lbRow,ubRow,output,options);
Error in MYRING_SYMS_optimisation_K (line 56) [z,fval,exitflag,output]
= particleswarm(objective,nVar,lb,ub,options)
Caused by:
Failure in initial objective function evaluation. PARTICLESWARM cannot continue.
The fun takes only one argument, which is a vector with nvars elements. From particleswarm doc:
x = particleswarm(fun,nvars) attempts to find a vector x that achieves a local minimum of fun. nvars is the dimension (number of design variables) of fun.
So you need to declare a new objective function that only takes 1 argument:
[z,fval,exitflag,output] = particleswarm( ...
#(x) objective(x(1), x(2), x(3)), ...
nVar,lb,ub,options)
Related
I want to find only real roots of the equation which is ;
4*sqrt((1-(z^2/f1^2))*(1-z^2))-(2-z^2)^2-(m*z^4*sqrt(1-z^2/f1^2)/ ...
sqrt(1-((z^2/f1^2)/y^2)))
I know that equation includes complex roots, but I do not want to see them. Moreover, my code fails and says that;
Error using fzero (line 242) Function values at interval endpoints
must be finite and real.
Error in scholte (line 21) x=fzero(fun,x0)
Here is my code;
rho2 = 1000; %kg/m3
rho1 = 2700; %kg/m3
cl2 = 1481; %m/s
cl1 = 5919; %m/s
m = rho2/rho1;
y = cl2/cl1;
poi = 0.25;
f1 = (sqrt((1-2*poi)/(2*(1-poi))))^-1;
fun = #(z) 4*sqrt((1-(z^2/f1^2))*(1-z^2))-(2-z^2)^2- ...
(m*z^4*sqrt(1-z^2/f1^2)/sqrt(1-((z^2/f1^2)/y^2)));
x0 = [1 10];
x = fzero(fun, x0)
I changed x0 interval many times, but it showed the same error. How can I fix my code?
Your problem, as Matlab tells you, is that Function values at interval endpoints must be finite and real, and in your case they are not real:
fun(x0(1))
ans =
-1.0000 + 0.1454i
Your function is probably just too complex for fzero to handle. However I am not an expert, lets see if someone with more knowledge than me can point you in the correct direction for solving that equation.
I am implementing the expression given in the image which is the log-likelihood for AR(p) model.
In this case, p=2. I am using fmincon as the optimization tool. I checked the documentation and other examples over internet regarding the syntax of this command. Still, I am unable to mitigate the problem. Can somebody please help in eliminating the problem?
The following is the error
Warning: Options LargeScale = 'off' and Algorithm = 'trust-region-reflective' conflict.
Ignoring Algorithm and running active-set algorithm. To run trust-region-reflective, set
LargeScale = 'on'. To run active-set without this warning, use Algorithm = 'active-set'.
> In fmincon at 456
In MLE_AR2 at 20
Error using ll_AR2 (line 6)
Not enough input arguments.
Error in fmincon (line 601)
initVals.f = feval(funfcn{3},X,varargin{:});
Error in MLE_AR2 (line 20)
[theta_hat,likelihood] =
fmincon(#ll_AR2,theta0,[],[],[],[],low_theta,up_theta,[],opts);
Caused by:
Failure in initial user-supplied objective function evaluation. FMINCON cannot
continue.
The vector of unknown parameters,
theta_hat = [c, theta0, theta1, theta2] where c = intercept in the original model which is zero ; theta0 = phi1 = 0.195 ; theta1 = -0.95; theta2 = variance of the noise sigma2_epsilon.
The CODE:
clc
clear all
global ERS
var_eps = 1;
epsilon = sqrt(var_eps)*randn(5000,1); % Gaussian signal exciting the AR model
theta0 = ones(4,1); %Initial values of the parameters
low_theta = zeros(4,1); %Lower bound of the parameters
up_theta = 100*ones(4,1); %upper bound of the parameters
opts=optimset('DerivativeCheck','off','Display','off','TolX',1e-6,'TolFun',1e-6,...
'Diagnostics','off','MaxIter', 200, 'LargeScale','off');
ERS(1) = 0.0;
ERS(2) = 0.0;
for t= 3:5000
ERS(t)= 0.1950*ERS(t-1) -0.9500*ERS(t-2)+ epsilon(t); %AR(2) model y
end
[theta_hat,likelihood,exit1] = fmincon(#ll_AR2,theta0,[],[],[],[],low_theta,up_theta,[],opts);
exit(1,1)=exit1;
format long;disp(num2str([theta_hat],5))
function L = ll_AR2(theta,Y)
rho0 = theta(1); %c
rho1 = theta(2); %phi1
rho2 = theta(3); %phi2
sigma2_epsilon = theta(4);
T= size(Y,1);
p=2;
mu_p = rho0./(1-rho1-rho2); %mean of Y for the first p samples
%changed sign of the log likelihood expression
cov_p = xcov(Y);
L1 = (Y(3:end) - rho0 - rho1.*Y(1:end-1) - rho2.*Y(1:end-2)).^2;
L = (p/2).*(log(2*pi)) + (p/2).*log(sigma2_epsilon) - 0.5*log(det(inv(cov_p))) + 0.5*(sigma2_epsilon^-1).*(Y(p) - mu_p)'.*inv(cov_p).*(Y(p) - mu_p)+...
(T-p).*0.5*log(2*pi) + 0.5*(T-p).*log(sigma2_epsilon) + 0.5*(sigma2_epsilon^-1).*L1;
L = sum(L);
end
You are trying to pass constant parameters to the objective function (Y) in addition to the optimization variables (theta).
The right way of doing so is using anonymous function:
Y = ...; %// define your parameter here
fmincon( #(theta) ll_AR2(theta, Y), theta0, [],[],[],[],low_theta,up_theta,[],opts);
Now the objective function, as far as fmincon concerns, depends only on theta.
For more information you can read about anonymous functions and passing const parameters.
i try to run the following in order to integrate numerically:
nu = 8;
psi=-0.2;
lambda = 1;
git = #(u) tpdf((0 - lambda * skewtdis_inverse(u, nu, psi)), nu);
g(t,i) = integral(git,1e-10,1-1e-10,'AbsTol',1e-16);
where tpdf is a matlab function and skewtdis:inverse looks like this:
function inv = skewtdis_inverse(u, nu, lambda)
% PURPOSE: returns the inverse cdf at u of Hansen's (1994) 'skewed t' distribution
c = gamma((nu+1)/2)/(sqrt(pi*(nu-2))*gamma(nu/2));
a = 4*lambda*c*((nu-2)/(nu-1));
b = sqrt(1 + 3*lambda^2 - a^2);
if (u<(1-lambda)/2);
inv = (1-lambda)/b*sqrt((nu-2)./nu)*tinv(u/(1-lambda),nu)-a/b;
elseif (u>=(1-lambda)/2);
inv = (1+lambda)/b*sqrt((nu-2)./nu).*tinv(0.5+1/(1+lambda)*(u-(1-lambda)/2),nu)-a/b;
end
What i get out is:
Error in skewtdis_inverse (line 6)
c = gamma((nu+1)/2)/(sqrt(pi*(nu-2))*gamma(nu/2));
Output argument "inv" (and maybe others) not assigned during call to "F:\Xyz\skewtdis_inverse.m>skewtdis_inverse".
Error in #(u)tpdf((0-lambda*skewtdis_inverse(u,nu,psi)),nu)
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 76)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in integral (line 89)
Q = integralCalc(fun,a,b,opstruct);
If i , however call the function in thr handle directly there are no Problems:
tpdf((0 - lambda * skewtdis_inverse(1e-10, nu, psi)), nu)
ans =
1.4092e-11
tpdf((0 - lambda * skewtdis_inverse(1-1e-10, nu, psi)), nu)
ans =
7.0108e-10
Your effort is highly appreciated!
By default, integral expects the function handle to take a vector input.
In your code, the if-statement creates a complication since the condition will evaluate to true only if all elements of u satisfy it.
So, if u is a vector that has elements both greater than and less than (1-lambda)/2, inv will never be assigned.
There are two options:
Put the if-statement in a for-loop and iterate over all of the elements of u.
Use logical indexes for the assignment.
The second option is faster for large element count and, in my opinion, cleaner:
inv = u; % Allocation
IsBelow = u < (1-lambda)/2; % Below the threshold
IsAbove = ~IsBelow ; % Above the threshold
inv(IsBelow) = (1-lambda)/b*sqrt((nu-2)./nu)*tinv(u(IsBelow)/(1-lambda),nu)-a/b;
inv(IsAbove) = (1+lambda)/b*sqrt((nu-2)./nu)*tinv(0.5+1/(1+lambda)*(u(IsAbove)-(1-lambda)/2),nu)-a/b;
I am using numerical integration in MATLAB, with one varibale to integrate over but the function also contains a variable number of terms depending on the dimension of my data. Right now this looks like the following for the 2-dimensional case:
for t = 1:T
fxt = #(u) exp(-0.5*(x(t,1)-theta*norminv(u,0,1)).^2) .* ...
exp(-0.5*(x(t,2) -theta*norminv(u,0,1)).^2);
f(t) = integral(fxt,1e-4,1-1e-4,'AbsTol',1e-3);
end
I would like to have this function flexible in the sense that there could be any number of data points in, each in the following term:
exp(-0.5*(x(t,i) -theta*norminv(u,0,1)).^2);
I hope this is understandable.
If x and u have a valid dimension match (vector-vector or array-scalar) for the subtraction, you can put the whole matrix x into the handle and pass it to the integral function using the name-parameter pair ('ArrayValued',true):
fxt = #(u) exp(-0.5*(x - theta*norminv(u,0,1)).^2) .* ...
exp(-0.5*(x - theta*norminv(u,0,1)).^2);
f = integral(fxt,1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
[Documentation]
You may need a loop if integral ever passes a vector u into the handle.
But in looking at how the integral function is written, the integration nodes are entered as scalars for array-valued functions, so the loop shouldn't be necessary unless some weird dimension-mismatch error is thrown.
Array-Valued Output
In response to the comments below, you could try this function handle:
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1)).^2),2);
Then your current loop would look like
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1)).^2),2);
k = 2;
for t = 1:T
f(t) = integral(#(u)fx(u,t,k),1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
end
The ArrayValued flag is needed since x and u will have a dimension mismatch.
In this form, another loop would be needed to sweep through the k indexes.
However, we can improve this function by skipping the loop altogether since each iterate of the loop is independent by using the ArrayValued mode:
fx = #(u,k) prod(exp(-0.5*(x(:,1:k)-theta*norminv(u,0,1)).^2),2);
k = 2;
f = integral(#(u)fx(u,k),1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
Vector-Valued Output
If ArrayValued is not desired, which may be the case if the integration requires a lot of subdivisions and a vector-valued u is preferable, you can also try a recursive version of the handle using cell arrays:
% x has size [T,K]
fx = cell(K,1);
fx{1} = #(u,t) exp(-0.5*(x(t,1) - theta*norminv(u,0,1)).^2);
for k = 2:K
fx{k} = #(u,t) fx{k-1}(u,t).*exp(-0.5*(x(t,k) - theta*norminv(u,0,1)).^2);
end
f(T) = 0;
k = 2;
for t = 1:T
f(t) = integral(#(u)fx{k}(u,t),1e-4,1-1e-4,'AbsTol',1e-3);
end
ThanksTroy but now I run into the follwing:
x = [0.3,0.8;1.5,-0.7];
T = size(x,1);
k = size(x,2);
theta= 1;
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k) - theta*norminv(u,0,1))^2));
for t = 1,T
f(t) = integral(#(u)fx(u,t,k),1e-4,1-1e-4,'AbsTol',1e-3);
end
Error using -
Matrix dimensions must agree.
Error in #(u,t,k)prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1))^2))
Error in #(u)fx(u,t,k)
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 76)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in integral (line 89)
Q = integralCalc(fun,a,b,opstruct);
I am dealing with the following code:
function opemployment=eqns(unknown);
global kappa varphi lgamma beta r delta s x b e theta v;
h=unknown(1);
gamma=unknown(2);
opemployment(1)=(h^(gamma-1))*((1-kappa)*((lgamma*(varphi^beta))/(gamma*kappa*beta+1-kappa))*h^(gamma*beta-gamma)-(r+delta+s)*(s^(gamma-1))*x^(-gamma));
opemployment(2)=(1-kappa)*(b-e+(kappa/(1-kappa))*theta*v^(gamma-1));
and then call:
close all; clear all;
global kappa varphi lgamma beta r delta s x b e theta v;
kappa = 0.1;
varphi = 2;
lgamma = 3;
beta = 0.9;
r = 2;
delta = 2 ;
s = 3;
x = 5;
b = 4;
e =3;
theta = 3 ;
v = 2;
guess = [0.7,0.3];
sol=fsolve('eqns',guess)
Yet, I receive the following error:
'Error using feval
Undefined function 'eqns' for input arguments of type 'double'.
Error in fsolve (line 217)
fuser = feval(funfcn{3},x,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation.
FSOLVE cannot continue.
I am a total MATLAB beginner and have no clue where the error lays.
You are not specifying the first parameter of fsolve correct. Taking a look at the documentation is always very useful when you're in doubt about how to call a function. For fsolve, it's here: http://www.mathworks.com/help/optim/ug/fsolve.html
In your case, for your fsolve statement, you must do this:
sol=fsolve(#eqns,guess)
fsolve expects a function handle to your function that you want to solve, not the actual name of the function itself.