Solve a non-linear system of equations with differentiation in Matlab - matlab

I would like to solve a system of non-linear equations in Matlab with fsolve, but I also have to differentiate the functions with respect to two variables. Here is the problem in steps:
Step 1: I define the system of non-linear functions F:
function F = root2d(x)
F(1) = (exp(-x(1)+2)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
F(2) = (exp(-x(2)+1)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
end
Step 2: I want to find the derivative of F(1) with respect to x(1) and the derivative of F(2) with respect to x(2) such that:
function F = root2d(x)
F(1) = (exp(-x(1)+2)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
F(2) = (exp(-x(2)+1)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
f1_d=diff(F(1),x(1))
f1_d=diff(F(2),x(2))
end
Step 3: I want my function to be the original one plus the derivative:
function F = root2d(x)
F(1) = (exp(-x(1)+2)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
F(2) = (exp(-x(2)+1)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
f1_d=diff(F(1),x(1));
f1_d=diff(F(2),x(2));
F(1)=F(1)+f1_d;
F(2)=F(2)+f2_d;
end
Step 4: In the main file I would use this function with fsolve to solve the system of non-linear equations for x(1) and x(2):
syms x
fun = #root2d;
x0 = [0,0];
x = fsolve(fun,x0);
root2d(x)
function F = root2d(x)
F(1) = (exp(-x(1)+2)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
F(2) = (exp(-x(2)+1)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
f1_d=diff(F(1),x(1));
f1_d=diff(F(2),x(2));
F(1)=F(1)+f1_d;
F(2)=F(2)+f2_d;
end
Can you please help me, how can a rewrite my code in order to solve the derivatives and then calculate and solve the system? Calculation of the derivates by hand is not an option because later I have to develop this program and I will have about 100 equations instead of 2.

A fundamental problem that you're making is that you're solving this system numerically with fsolve but then mixing in symbolic math.
Since your functions, F don't seem to vary, their derivatives shouldn't either, so you can create them as symbolic functions and calculate their derivatives symbolically once:
syms x [1 2] real; % Create 1-by-2 symbolic vector
F = exp(-x+2)/(1+exp(-x(1)+2)+exp(-x(2)+1));
F_d(1) = diff(F(1),x(1));
F_d(2) = diff(F(2),x(2));
F = F+F_d; % Add derivatives to original functions
Then you can convert these to a numerical form and solve with fsolve:
root2d = matlabFunction(F,'Vars',{x}); % Convert symbolic function to vectorized numeric function
x0 = [0 0];
x = fsolve(root2d,x0)
root2d(x)
Note that fsolve only finds a single root (if it succeeds) for a given initial guess. It's strongly suggested that you plot your function to understand it's behavior and how many roots it may have. From my limited plotting it doesn't look like this function, as defined above, has any zeros. Separately, you should also look into the tolerance options for fsolve.
You can look into purely numerical (non-symbolic) methods to solve this, but you'll need properly calculate the derivative numerically. You might look into this approach for that.

Related

How to numerically solve for the upper bound of a definite integral in Matlab?

Given the equation
For some given function f(x) where gamma is also given, how can you numerically solve for upper bound u in Matlab?
f(x) can be a placeholder for any model.
This is a root-finding and integration problem but with my lack of knowledge in Matlab, I'm still trying to figure out how it is done.
My initial solution is a brute force approach. Let's say we have
and gamma = 0.8, we can find the definite integral from -inf to u by extracting its integral from some very small value u, working our way up until we reach a result gamma = 0.8.
syms f(x)
f(x) = (1/(sqrt(6*pi)))*exp(-(x^2/6));
gamma = 0.8;
u = -10;
res = int(f,x,-Inf,u);
while double(res) <= gamma
u = u+0.1;
res = int(f,x,-Inf,u);
end
fprintf("u is %f", u);
This solution is pretty slow and will definitely not work all the time.
I set u = 10 because looking at the graph of the function, we don't really get anything outside the interval [-5, 5].
You can use MATLAB Symbolic Math Toolbox (an addon you might need to install).
That way you can define yourself a "true" unknow variable x (not an array of x-values) and later integrate from negative infinity:
syms f(x)
f(x) = exp(2*x) % an example function
gamma = int(f,x,-Inf,u)
This yields gamma as the integral from -Inf to u, after defining f(x) as a symbolic function and u as a scalar

Solve complex matrix equation

I have a complex equation involving matrices:
R = expm(X)*A + (expm(X)-I)*inv(X)*B*U;
where R, B and U are known matrices.
I is an identity matrix.
I need to solve for X. Is there any way to solve this in MATLAB?
If your equation is nonlinear and you have access to MATLAB optimization toolbox you can use the fsolve function (You can still use it for a linear equation, but it may not be the most efficient approach). You just need to reformat your equation into the form F(x) = 0, where x is a vector or a matrix. For example, if X is a vector of length 2:
Define your function to solve:
function F = YourComplexEquation(X)
Fmatrix = expm(X)*A + (expm(X)-I)*inv(X)*B*U - R
% This last line is because I think fsolve requires F to be a vector, not a matrix
F = Fmatrix(:);
Then call fsolve with an initial guess:
X = fsolve(#YourComplexEquation,[0;0]);

Using "subs" Function to Evaluate Output of "dsolve" Give Extra Output in Maltab

Introduction
If you want to know the grand scheme... read the introduction. If not, Just skip down to My Problem.
I have a project for my Differential Equations and Linear Algebra course where I have to use a computer algebra system to solve both linear, ordinary differential equations of the first degree with constant coefficients and a non-linear ODE with constant coefficients. I have to show this being done both analytically and numerically. My plan is to have 2 functions that make use of the dsolve function for the analytical part and a function called ODE1 I learned about through this tutorial by Matlab. This function is defined to approximate the solution to the differential equation using Euler's Method. The functions would all use the same input parameters so each input could be defined once and the functions would all understand what inputs to use (maybe nest the functions under one calling function). The goal is to evaluate the analytical solution over the same interval being used to find the numerical approximation and compare the results in both a table and graph. I got the numerical solution to give me a "table" in the form of a row vector and also graph that row vector. I began having an issue with the Analytic solution...
My Problem
To solve a linear ODE of the first order, I generated this function
function [s1] = L_Analytic(eqn,t0,h,numstep,y0)
% eqn is the differential equation to be solved
% t0 is the start of the interval that the resulting equation is to be evaluated at
% h is the stepsize
% numstep is the number of steps
% y0 is the initial condition
syms y(x)
cond = y(0) == y0;
A = dsolve(eqn,cond);
s1 = A;
S1 = s1;
for t = t0 : h : h*(numstep-2)
S1 = [subs(S1); vpa(subs(s1))]
end
end
The list generated by this function L_Analytic(diff(y)==y, 0, 0.1, 5, 1) is
1
1.0
1.105170...
1.221402...
1.349858...
When using the numerical method in a different function in Matlab using the same inputs, I get the list:
1.0000
1.1000
1.2100
1.3310
1.4641
For those who know their way around differential equations or are proficient in calculus, the solution to y' = y is e^x, and when evaluated over the interval 0:0.4 using 5 steps, the list should be
1
1.105...
1.2214...
1.3498...
1.4918...
after some rounding.
So the issue here is that I have an extra entry of 1 in my analytical solutions. I'm confident it has something to do with the subs(S1) part of S1 = [subs(S1); vpa(subs(s1))] in the for loop but I am stumped as to how to fix this.
I kind of understand why I need to use the subs function, in that I am using symbolic variables to use the dsolve function which outputs symbolic variables in its answer. Also, in order for the for loop to iterate and change, the symbolic variables must be substituted for real values of t each time. I did try moving the vpa(subs(s1)) just before the for loop, but this just returned the same value in the vector 5 times. I also tried not using subs(S1) and it gave me
exp(t)
1.0
1.1051709...
1.2214027...
1.3498588...
so I'm positive it's this part of the code.
Side Note: I understand the analytical method outputs a column vector as does the ODE1 shown in the video that's linked. In order to have Matlab plot this as one line, I transposed the column vector to make a row vector and will do the same with the analytical solution once the solution part is fixed.
By changing the internals of the for loop I made it work. My final function code turned out to be this:
function [s1] = L_Analytic3(eqn,t0,h,numstep,y0)
%Differential Equation solver for specific inputs
% eqn is the differential equation
% t0 is start of evaluation interval
% h is stepize
% numstep is the number of steps
% y0 is the initial condition
syms y(x)
cond = y(0) == y0;
A = dsolve(eqn, cond);
s1 = A;
S1 = s1;
for x = t0 : h : h*(numstep)
subs(x);
if x == t0
S1 = subs(s1,x);
else
S1 = [subs(S1), subs(s1,vpa(x))];
end
end
end

MATLAB: How to solve high dimensional nonlinear ODE?

I have an ODE:
x' = -x + f(x)
Looks simple enough, but x is 100 dimensional i.e.
x = [x1, ... , x100]
Furthermore,
fi(x) = ln(xi)/(ln(x1)+...+ln(x100))
where i is between 1 and 100 and f(x) = [f1(x), ... , f100(x)]
On MATLAB's website, it says I should first create a function as:
But how can I do this? I have 100 variables, and all my variables are coupled through that highly nonlinear function.
Any help is greatly appreciated!
The function can leverage the vectorization capabilities of MATLAB since, from the ode45 documentation, the "function dydt = odefun(t,y), for a scalar t and a column vector y, must return a column vector dydt". So your odefun can be expressed simply as
function dxdt = odefun(~,x)
logX = log(x);
dxdt = -x + logX/sum(logX);
end
and let ode45, or another appropriate integrator, handle the rest.

Differential Equation ODE

I have a problem with some differential equations of first-order.
I'm trying to solve them with ode23 and ode23s.
The differential equations are:
y'+3y+z=0
z'-y+z=0
with the initial values:
y(0)=1 and z(0)=1
I also want to compare it with the analytical solution:
y=exp(-2x)(1-2x)
z=exp(-2x)(1+2x)
I want to do it this way because I need to do the comparison in order to choose the better solver: ode23 or ode23s, whichever one is closer to the analytical solution.
My code is:
function dy=projectb1(t,y)
%y'=-4y
%z'= 0
%y(1)=y'
%y(2)=z'
dy = [-4*y(2); 0*y(1)];
and:
% Comparison of analytical solution
clear
options= odeset('RelTol',1e-4,'AbsTol', [1e-4 1e-4]);
%figure
%t1=cputime;
[t23,y23]= ode23('projectb1',[0 12],[1 1],options);
[t23s,y23s]= ode23s('project1',[0 20],[1 0],options);
%tobl = cputime -t1
figure
ya=exp(-2*t23).*(1-2*t23);
za=exp(-2*t23).*(1+2*t23);
plot(t23,ya,za,'r',t23,y23(:,1),'g-.',t23s,y23s(:,1),'b');
%legend('ya','ode23','ode23s',0)
text(3.4,-1.7,'ya')
title('\bf{Analytical and numerical solutions using} \it{ode23s, ode23}')
But it doesn't work. Could someone help me?
The error Matlab throws right away has to do with the line
plot(t23,ya,za,'r',t23,y23(:,1),'g-.',t23s,y23s(:,1),'b');
This should be
plot(t23,ya,t23,za,'r',t23,y23(:,1),'g-.',t23s,y23s(:,1),'b');
You missed that extra t23.
Another problem appears to be in the definition of the differential equation.
For systems of differential equations, the Matlab ODE suite passes a vector x whose components are the values of the functions you are attempting to approximate.
Therefore, as in the example below, the first component of x is the value of y at time t, and the second component of x is the value of z at time t:
function dx = projectb1(t,x)
y = x(1);
z = x(2);
dy = -3*y - z;
dz = y - z;
dx = [dy;dz];
end
I changed the input y to x to make it clear that what is input is a vector of values of y and z.
Also, note that while ode23 has the initial conditions [1,1], ode23s has [1,0], which means it is solving a different initial value problem.