Evaluate symbolic function in Matlab - matlab

I've defined a function in Matlab like this:
clg = 2*pi*(alpha-alphai+0.5*A(1));
where A is an array which depends on alpha.
I want to evaluate clg for aplha=0.53.
I've tried subs(clg, alpha, 0.53), but It gives me a bunch of weird errors:
Error using sym/subs>normalize (line 210)
Entries in second argument must be scalar.
Error in sym/subs>mupadsubs (line 136)
[X2,Y2,symX,symY] = normalize(X,Y); %#ok
Error in sym/subs (line 124)
G = mupadsubs(F,X,Y);
Error in integral (line 45)
subs(clg, alpha, 0.53)
Any idea on how to achieve that?
Thanks!

I have no problem about your question.
>> syms x x1 x2
>> clg = 2*pi*(x-x1+0.5*x2);
>> subs(clg,x,0.53)
ans =
2*pi*(x2/2 - x1 + 53/100)

I am trying to reproduce the problem, but this works:
syms x
%A is a symbolic matrix that depends on x
A = inv([10*x, 2*x, 3*x;
4*x, 10, 6*x;
7*x, 8*x, 10*x])
%y is a symbolic expression defined such that
%it depends on A, but collapses to an expression of x
y = x + 0.5*A(2,2)
%subs returns a symbolic (in this case fraction) evaluation:
subs(y, x, 3)
%eval returns a numeric evaluation:
x = 3
eval(y)
(I have encountered the same error message as you in my own code, but have not yet hunted down its source.)

Related

Matlab Pso Algorithm

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)

Error while solving system of equations

I received a negative MATLAB response while inserting the following requests:
syms x y z
solve (x+y==z,x-2*y==z,[x,y],'ReturnConditions', false)
I wanted to get x, and y in terms of z but, alas, I got the following error:
??? Error using ==> char
Conversion to char from logical is not possible.
Error in ==> solve>getEqns at 160
vc = char(v);
Error in ==> solve at 84
[eqns,vars] = getEqns(varargin{:});
Any help please?
Try using a cell array to wrap x and y instead:
>> syms x y z
>> X = solve (x+y==z,x-2*y==z,{x,y},'ReturnConditions', false);
>> X.x
ans =
z
>> X.y
ans =
0
This was required for previous versions of MATLAB. However, I'm using R2015a currently and your code works for me. I can't replicate your error. You may be using a previous version.
I think i found the hit-back to my problem.
As for solving system of two equations and two variables, we use a matrix of inputs, and outputs must be sprecified.
b=[x+y-z;x-3*y-z;]
b =
x + y - z
x - 3*y - z
[e t]=solve(b,x,y)
e =
z
t =
0
Thnk you all.

MATLAB strange error Gamma function numerical integration

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;

Create flexible function handle

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);

Plotting symbolic function in MatLab

I've some problems in plotting a symbolic function in MatLab: for example when I try to plot the function f with ezplot, where:
f = 9/2 - ((2*x)/5 - 2/5)*(x/3 - 17/6) - x
I get the following error:
Error using findstr
Inputs must be character arrays.
Error in ezplot>ezplot1 (line 442)
if (isa(f, 'inline') && ~isempty(findstr(char(f), '=')))
Error in ezplot (line 145)
[hp, cax] = ezplot1(cax, f{1}, vars, labels, args{:});
Error in sym/ezplot (line 61)
h = ezplot(fhandle(f));
I've tried to convert the symbolic function f in the char form but it returns an analogous error:
Error using findstr
Inputs must be character arrays.
Error in ezplot>ezplot1 (line 442)
if (isa(f, 'inline') && ~isempty(findstr(char(f), '=')))
Error in ezplot (line 145)
[hp, cax] = ezplot1(cax, f{1}, vars, labels, args{:});
Thanks for any help!
You must have some problem with you function definition. Perhaps x has been defined incorrectly?
The following works, at least in Matlab 2010b. It defines f as a symbolic function of the symbolic variable x:
>> clear all
>> syms x
>> f = 9/2 - ((2*x)/5 - 2/5)*(x/3 - 17/6) - x;
>> ezplot(f)
The following is also valid. It defines f as a string:
>> clear all
>> f = '9/2 - ((2*x)/5 - 2/5)*(x/3 - 17/6) - x';
>> ezplot(f)
What if you define your function as an anonymous function:
myfun = #(x) 4.5 - (((2*x)/5 - 2/5)*(x/3 - 17/6) - x);
figure
ezplot(myfun)
I really don't know why the ezplot command doesn't work with my Matlab 2012b, so I had to go with a brutal solution like this :(
syms x
f = 9/2 - ((2*x)/5 - 2/5)*(x/3 - 17/6) - x;
k = 0.1;
x_p = 0:k:10;
y_p = subs(f,x,x_p);
plot(x_p,y_p)