Matlab symbolic function with normcdf - matlab

I have the following function for which I want to find the extrema using matlab.
That function has to use the "normcdf" function in matlab in order to get the results but when I'm trying to create the symbolic function I get back some errors.
The input I give is the following:
syms z fz t sz
fv = 1000 * ((z * fz * normcd(t,fz,sz)) / (20 * 50 * normcd(t,50,20))) + 1000 * normcdf((20 * 50 * normcd(t,50,20) + z * fz * normcd(t,fz,sz)) / 2000, 50 * normcd(t,50,20), 20) - 10 * z
and the errors I get back are the following:
??? Error using ==> sym.le at 11
Function 'le' is not implemented for MuPAD symbolic objects.
Error in ==> normcdf at 57
sigma(sigma <= 0) = NaN;
Does anyone know how I can get around that? Thanks in advance.
I forgot to mention that I use matlab version R2009a.

It appears to work for me:
>> syms z fz t sz
>> fv = 1000 * ((z * fz * normcdf(t,fz,sz)) / (20 * 50 * normcdf(t,50,20))) + 1000 * normcdf((20 * 50 * normcdf(t,50,20) + z * fz * normcdf(t,fz,sz)) / 2000, 50 * normcdf(t,50,20), 20) - 10 * z
>> subs(fv,{fz,sz,t,z},{1,2,3,4});
ans =
809.2922
Take a look at the Subs.

I found a way around it. Instead of using normcdf one can use its equivalent equation with erf which then works fine.
normcdf(x,mu,sig) = (1+erf((x-mu)/sig/sqrt(2)))/2

Related

ODE45 with very large numbers as constraints

2nd ODE to solve in MATLAB:
( (a + f(t))·d²x/dt² + (b/2 + k(t))·dx/dt ) · dx/dt - g(t) = 0
Boundary condition:
dx/dt(0) = v0
where
t is the time,
x is the position
dx/dt is the velocity
d2x/dt2 is the acceleration
a, b, v0 are constants
f(t), k(t) and h(t) are KNOWN functions dependent on t
(I do not write them because they are quite big)
As an example, using symbolic variables:
syms t y
%% --- Initial conditions ---
phi = 12.5e-3;
v0 = 300;
e = 3e-3;
ro = 1580;
E = 43e9;
e_r = 0.01466;
B = 0.28e-3;
%% --- Intermediate calculations ---
v_T = sqrt(((1 + e_r) * 620e6) /E) - sqrt(E/ro) * e_r;
R_T = v_T * t;
m_acc = pi * e * ro *(R_T^2);
v_L = sqrt (E/ro);
R_L = v_L * t;
z = 2 * R_L;
E_4 = B * ((e_r^2)* B * (0.9^(z/B)-1)) /(log(0.9));
E_1 = E * e * pi * e_r^2 * (-phi* (phi - 2*v_T*t)) /16;
E_2 = pi * R_T^2 * 10e9;
E_3 = pi * R_T^2 * 1e6 * e;
%% Resolution of the problem
g_t = -diff(E_1 + E_2 + E_3, t);
f(t,y)=(g_t - (pi*v_T*e*ro/2 + E_4) * y^2 /(y* (8.33e-3 + m_acc))];
fun=matlabFunction(f);
[T,Y]=ode45(fun,[0 1], v0]);
How can I rewrite this to get x as y=dx/dt? I'm new to Matlab and any help is very welcome !
First, you chould use subs to evaluate a symbolic function. Another approach is to use matlabFunction to convert all symbolic expressions to anonymous functions, as suggested by Horchler.
Second, you're integrating the ODE as if it is 1st order in dx/dt. If you're interested in x(t) as well as dx/dt(t), then you'll have to modify the function like so:
fun = #(t,y) [y(2);
( subs(g) - (b/2 + subs(k))*y(2)*y(2) ) / ( y(2) * (a + subs(f))) ];
and of course, provide an initial value for x0 = x(0) as well as v0 = dx/dt(0).
Third, the absolute value of the parameters is hardly ever a real concern. IEEE754 double-precision floating point format can effortlessly represent numbers between 2.225073858507201e-308 and 1.797693134862316e+308 (realmin and realmax, respectively). So for the coefficients you gave (O(1014)), this is absolutely not a problem. You might lose a few digits of precision if you don't take precautions (rescale to [-1 +1], reformulate the problem in different units, ...), but the relative error due to this is more than likely to be tiny and insignificant compared to the algorithmic error made by ode45.
<RANDOM_OPINIONATED_RANT>
Fourth, WHY do you use symbolic math for this purpose?! You are doing a numerical integration, meaning, there is no analytic solution anyway. Why bother with symbolics then? Doing the integration with symbolics (through vpa even) is going to be dozens, hundreds, yes, often even thousands of times slower than keeping (or re-implementing) everything numerical (which some would argue is already slow in MATLAB compared to a bare-metal approach).
Yes, of course, for this specific, individual, isolated use case it may not matter much, but for the future I'd strongly advise you to learn to:
use symbolics for derivations, proving theorems, simplifying expressions, ...
use numerics to implement any algorithm or function from which actual numbers are expected.
In other words, symbolics for drafting, numerics for crunching. And exactly zero symbolics should appear in any good implementation of any algorithm.
Although it's possible to mix them to some extent, that does not mean it is a good idea to do so. In fact, that's almost never. And the few isolated cases where it is the only viable option are not a vindication of the approach.
They are rare, isolated cases after all, far from the abundant norm.
For me it bears resemblance with the evil eval, with similar reasons for why it Should. Be. Avoided.
</RANDOM_OPINIONATED_RANT>
With the full code, it's easy to come up with a complete solution:
% Initial conditions
phi = 12.5e-3;
v0 = 300;
x0 = 0; % (my assumption)
e = 3e-3;
ro = 1580;
E = 43e9;
e_r = 0.01466;
B = 0.28e-3;
% Intermediate calculations
v_T = sqrt(((1 + e_r) * 620e6) /E) - sqrt(E/ro) * e_r;
R_T = #(t) v_T * t;
m_acc = #(t) pi * e * ro *(R_T(t)^2);
v_L = sqrt (E/ro);
R_L = #(t) v_L * t;
z = #(t) 2 * R_L(t);
E_4 = #(t) B * ((e_r^2)* B * (0.9^(z(t)/B)-1)) /(log(0.9));
% UNUSED
%{
E_1 = #(t) -phi * E * e * pi * e_r^2 * (phi - 2*v_T*t) /16;
E_2 = #(t) pi * R_T(t)^2 * 10e9;
E_3 = #(t) pi * R_T(t)^2 * 1e6 * e;
%}
% Resolution of the problem
g_t = #(t) -( phi * E * e * pi * e_r^2 * v_T / 8 + ... % dE_1/dt
pi * 10e9 * 2 * R_T(t) * v_T + ... % dE_2/dt
pi * 1e6 * e * 2 * R_T(t) * v_T ); % dE_3/dt
% The derivative of Z = [x(t); x'(t)] equals Z' = [x'(t); x''(t)]
f = #(t,y)[y(2);
(g_t(t) - (0.5*pi*v_T*e*ro + E_4(t)) * y(2)^2) /(y(2) * (8.33e-3 + m_acc(t)))];
% Which is readily integrated
[T,Y] = ode45(f, [0 1], [x0 v0]);
% Plot solutions
figure(1)
plot(T, Y(:,1))
xlabel('t [s]'), ylabel('position [m]')
figure(2)
plot(T, Y(:,2))
xlabel('t [s]'), ylabel('velocity [m/s]')
Results:
Note that I've not used symbolics anywhere, except to double-check my hand-derived derivatives.

How to create, solve and plot conditional function in matlab

For example,
I have a
f(x)=
9+4(x+3), if -4<=x<-1 (subf1)
7-9(x-0.4), if -1<=x<1 (subf2)
How can I create a function of f(x) in matlab?
I tried
f=0
syms x
f=f+ subf1 with heaviside+ subf2 with heaviside
But I cannot give a v to solve f(v) and I cannot plot f(x) only from -4 to 1.
So is there another way to write conditional function?
Sorry my description is a little hard to follow. If you don't understand what I am asking, please let me know and I will try to rephrase. Thank you!
Depends on what you want to do with it. If for some reason you need symbolic, here is one way to write your symbolic function:
syms x
f1 = (9 + 4 * (x + 3)) * heaviside(x + 4) * (1 - heaviside(x + 1));
f2 = (7 - 9 * (x - 0.4)) * heaviside(x + 1) * (1 - heaviside(x - 1));
f = symfun(f1 + f2, x);
Otherwise, you can write your function in a file as:
function out = f(x)
out = (9 + 4 * (x + 3))*(x>=-4)*(x<-1) + (7 - 9 * (x - 0.4))*(x>=-1)*(x<1);
Or you can define it as an anonymous function:
f = #(x) (9 + 4 * (x + 3))*(x>=-4)*(x<-1) + (7 - 9 * (x - 0.4))*(x>=-1)*(x<1);
Then, you can plot any of the functions using, for instance, fplot:
fplot(f, [-4, 1])

Solving Non-linear System of 3 differentail equations(Lorenz equations) using ode solve: ode23s in Matlab

I am trying to solve 3 differentail equations(Lorenz equations) using ode solver: ode23s in Matlab. Here are the 3 lorenz equations:
dc/dt= alpha*I*(1-c) + c*(- k_f - k_d - k_n * s - k_p*(1-q))
ds/dt = lambda_b * c* P_C *(1-s)- lambda_r *(1-q)*s
dq/dt = (1-q)* k_p * c *(P_C / P_Q)- gamma * q
I have used the ode solver and created two M-files ode.m and lorenz.m
=> Here are my two Matlab M-files. This is my 1st M-file : ode.m which i ran to plot the graph.
format bank
close all;
clear all;
clc;
%time interval
ti=0;
tf=140;
tspan=[ti tf];
x0=[0.25 0.02 0.98]; %initial vectors
%time interval of [0 2] with initial condition vector [0.25 0.02 0.02] at time 0.
options= odeset('RelTol',1e-4, 'AbsTol',[1e-4 1e-4 1e-4]);
[t,x]= ode23s('lorenz',tspan,x0,options);
%Plotting the graphs:
figure
subplot(3,1,1), plot(t,x(:,1),'r'),grid on;
title('Lorenz Equations'),ylabel('c');
subplot(3,1,2), plot(t,x(:,2),'b'),grid on;
ylabel('s');
subplot(3,1,3), plot(t,x(:,3),'g'),grid on;
ylabel('q');xlabel('t')
This is my second M-file which is lorenz.m
% Creating the MATLAB M-file containing the Lorenz equations.
function xprime= lorenz(t,x)
%values of parameters
I=1200;
k_f= 6.7*10.^7;
k_d= 6.03*10.^8;
k_n=2.92*10.^9;
k_p=4.94*10.^9;
lambda_b= 0.0087;
lambda_r =835;
gamma =2.74;
alpha =1.14437*10.^-3;
P_C= 3 * 10.^(11);
P_Q= 2.87 * 10.^(10);
% initial conditions
c=x(1);
s=x(2);
q=x(3);
%Non-linear differential equations.
% dc/dt= alpha*I*(1-c) + c*(- k_f - k_d - k_n * s - k_p*(1-q))
% ds/dt = lambda_b * c* P_C *(1-s)- lambda_r *(1-q)*s
% dq/dt = (1-q)* k_p * c *(P_C / P_Q)- gamma * q
xprime=[ alpha*I*(1-c) + c*(- k_f - k_d - k_n * s - k_p*(1-q)); lambda_b *(1-s)* c* P_C - lambda_r *(1-q)*s; (1-q)*k_p * c *(P_C / P_Q)- gamma * q];
Please help me, both M-files codes are working but i want to use function handle (#lorenz) in lorenz.m file because Lorenz isn’t very descriptive of this problem. And also, when i run ode.m file , the values of plot are really small but when i run the lorenz.m file , the values of c,s,q are really big.I want to get values of s and q somewhere between 0 to 1. And value of c should be really big number something 3.5 X10^11. I don't know what is going on?
Your function is incorrect as far as I can see. This line:
xprime=[ alpha*I*(1-c) + c*(- k_f - k_d - k_n * s - k_p*(1-q)); lambda_b * c* P_C - lambda_r *(1-q)*s; k_p * c *(P_C / P_Q)- gamma * q];
should be:
xprime=[ alpha*I*(1-x(1)) + x(1)*(- k_f - k_d - k_n * x(2) - k_p*(1-x(3))); lambda_b * x(1)* P_C - lambda_r *(1-x(3))*x(2); k_p * x(1) *(P_C / P_Q)- gamma * x(3)];
You can then get rid of these lines in the function (initial conditions are passed via the call to ode15s):
%initial vectors
c=0.25;
s=0.02;
q=0.02;

Convert output from symbolic math (sym) to float

My question is similar to this question but I believe it to be more general.
I use Matlab's symbolic math toolbox to solve an equation:
MAZ = 0.5;
MAU = 1.0;
XI = 1.0;
ALPHA = 2.0;
DRG = 0.5;
SRG = 1.0;
PHI = 1 / (2 * MAU);
syms L;
f = 1 - DRG - sqrt(1 + (ALPHA * XI - L / (2 * XI * PHI) ) ^ 2 ) / ...
sqrt(1 + (ALPHA * XI) ^ 2) + L / (4 * PHI * SRG * sqrt(1 + (ALPHA * XI)^2));
a = solve(f,L,'Real',true);
The answer is:
a =
5^(1/2)/3 + (10*((4*5^(1/2))/25 + 6/25)^(1/2))/3 + 8/3
5^(1/2)/3 - (10*((4*5^(1/2))/25 + 6/25)^(1/2))/3 + 8/3
How do I automatically convert these expressions for a - which do not contain any symbolic expressions - to floats so that I can access them later in my code?
Matlab's symbolic math toolbox contains a function called double.
This function converts the result of the solve function - which is a sym - to a double:
double(a)
ans =
5.98921078320145
0.834834535131742
While double is correct, it is limited to the precision of 64bit floating points. Use vpa if a higher precision is needed:
>> vpa(a)
ans =
5.9892107832014511063435699584181
0.83483453513174202459587915406938
>> digits(99)
>> vpa(a)
ans =
5.98921078320145110634356995841813862213621375395128614574627036653958858547362556353272837962692249
0.834834535131742024595879154069378868157531819123064337100994463734092031618244369410214559292265698

MATLAB: Why does solve return an empty sym object?

I´m trying to solve this set of equations in MATLAB and I get an empty sym object:
equations = {'I2B+I2EQAB=I22B+I2EQBC',...
'I2A=I2EQAB+I2EQAC+I22A',...
'I2C+I2EQBC+I2EQAC=I22C',...
'I22B=IZB+IC1B',...
'IZB=IC2B+IZBB',...
'I22C=-I2C*Z2C*YC/2+IZC',...
'IZC=IC2C+IZCC',...
'I22A=IC1A+IZA1',...
'IC4A+IZA2=IZBB+IZCC',...
'IZB*Z2LB+IC2B*2/YB=IC1B*2/YB',...
'I2C*Z2C=-IC2C*2/YC+IZC*Z2LC',...
'IZA1*m*Z2LA+IC2A*2/(m*YA)=IC1A*2/(m*YA)',...
'IC4A*2/((1-m)*YA)=IC2A*2/(m*YA)+IZA2*(1-m)*Z2LA',...
'I2EQBC*Z2EQBC+IZC*Z2LC=IZB*Z2LB',...
'I2B*Z2B+IC1B*2/YB',...
'I2C*Z2C+IC1C*2/YC',...
'I2A*Z2A+IC1A*2/(m*YA)',...
'IZB*Z2LB+(1-m)*Z2LA*IZA2=IZA1*m*ZL2A-I2EQAB*Z2EQAB',...
'IZA1*m*Z2LA=IZA2*(1-m)*Z2LA+IZC*Z2LC+I2EQAC*Z2EQAC',...
'IC4A/((1-m)*YA)=IC2C/YC'};
variables = {'m','I2A','I2B','I2C','I2EQAB','I2EQAC','I2EQBC',...
'IZA1','IC1A','IC2A','IZA2','IC4A','IC1B','IZB',...
'IC2B','IZBB','IZC','IC2C','IZCC'};
LL = solve(equations{:},variables{:})
Can you help me figure out what's going wrong?
Warning: 20 equations in 19 variables.
> In solve at 139
Warning: Explicit solution could not be found.
> In solve at 170
LL =
[ empty sym ]
I think that's self explanatory, if not check out the documentation related to DSOLVE where:
Diagnostics If dsolve cannot find an
analytic solution for an equation, it
prints the warning: Warning: Explicit
solution could not be found. and
returns an empty sym object.
solve() has issues with variable names in capital letters, as yours.
Please refer to http://www.mathworks.com/matlabcentral/newsreader/view_thread/303201
I tried reformatting the equations and inputting directly into the symbolic toolbox, and the solve function just spits out all the equations, so it cannot solve for those variables as the current equations stand.
Do you have any knowledge about the domains or constraints for all those variables? If you do I'd look at specifying all those, perhaps it would allow the solver to find a solution for you.
To get you quickly up and running in the symbolic toolbox, here's your equations reformatted to fit:
equations := {
I2B + I2EQAB = I22B + I2EQBC,
I2A = I2EQAB + I2EQAC + I22A,
I2C + I2EQBC + I2EQAC = I22C,
I22B = IZB + IC1B,
IZB = IC2B + IZBB,
I22C = -I2C * Z2C * YC / 2 + IZC,
IZC = IC2C + IZCC,
I22A = IC1A + IZA1,
IC4A + IZA2 = IZBB + IZCC,
IZB * Z2LB + IC2B * 2 / YB = IC1B * 2 / YB,
I2C * Z2C = -IC2C * 2 / YC + IZC * Z2LC,
IZA1 * m * Z2LA + IC2A * 2 / (m * YA) = IC1A * 2 / (m * YA),
IC4A * 2 / ((1 - m) * YA) = IC2A * 2 / (m * YA) + IZA2 * (1 - m) * Z2LA,
I2EQBC * Z2EQBC + IZC * Z2LC = IZB * Z2LB,
I2B * Z2B + IC1B * 2 / YB,
I2C * Z2C + IC1C * 2 / YC,
I2A * Z2A + IC1A * 2 / (m * YA),
IZB * Z2LB + (1 - m) * Z2LA * IZA2 = IZA1 * m * ZL2A - I2EQAB * Z2EQAB,
IZA1 * m * Z2LA = IZA2 * (1 - m) * Z2LA + IZC * Z2LC + I2EQAC * Z2EQAC,
IC4A / ((1 - m) * YA) = IC2C / YC
}:
variables := {
m, I2A, I2B, I2C, I2EQAB, I2EQAC ,I2EQBC,
IZA1, IC1A, IC2A, IZA2, IC4A, IC1B, IZB,
IC2B, IZBB, IZC, IC2C, IZCC
}:
solve(equations, variables)
To specify that all your known variables are real numbers, use this command:
assume(variables, Type::Real)
Also note that I count 36 unique variables (unless I made a mistake) in the equations, you'd be getting a huge list of "what-if's" for those equations if the solver was able to produce a result. I'd look at your equations and see if you could group them out and solve them in smaller sets.
Matlab, symbolic solve: solve()
I think has issues with symbolic variables who's names are more than one character.
a-z works, but anytime i try to solve something with two letters or more it just spits
back out the empty set.
For instance, something as simple as solve('xy*10 = 1', 'xy') doesn't work :(