I have a task of writing an M script that would set up (and finally solve) a set of 19 differential equations and all of the equation coefficients. I am not sure what is the best way to input those equations.
Example of some equations:
Example of coefficients:
I don't think that this would be suited for Simulink. Other examples use a function in the form of #(t,x) where t is time and x the vector of all variables.
There are loads of "examples" online, but they don't seem to be appropriate for such a large set of large equations.
For example this exmple of solving 3 equatons
Even for 3 simple equations as they have solved, the functions are getting messy:
f = #(t,x) [-x(1)+3*x(3);-x(2)+2*x(3);x(1)^2-2*x(3)];
Using this notation and getting to the x(19) and cross-referencing all instances of x would be a mess.
I would like your help, and a simple example of how could I write these equations line by line, maybe using the symbolic toolbox, and then put them in an array that I can then forward to the solver.
As I said, I know there are examples online, but they tackle only the most basic system, and really they don't scale well if you want a clean and easily readable code.
I would like to have a similar to Wolfram alpha, where you type variable names as they are (instead od x(1), x(2), ... m x(19)) and if it's possible to get all solution vectors with their variable names.
You don't have to use an anonymous function handle as an ode function, you can create a separate function file (as shown in the odefun section of ode45.
For example, your odefun can look like:
function dy = myode(t,y)
% first unpack state variables
i_d2 = y(1);
i_q2 = y(2);
...
gamma2 = y(end-1);
omega2 = y(end);
% determine all constants
c34 = expression_for_c34;
...
c61 = expression_for_61;
% determine state derivative
i_d2_dot = expression;
...
omega2_dot = expression;
% pack state derivative based on order in state vector
dy(1) = i_d2_dot;
...
dy(end) = omega2_dot;
end
From this myode function you can also call other functions to e.g. determine the value for some coefficients based on the current state. Next, integrate the system using a suitable ode solver:
[t,y] = ode45(#myode,tspan,y0);
Related
I want to minimize a function like below:
Here, n can be 5,10,50 etc. I want to use Matlab and want to use Gradient Descent and Quasi-Newton Method with BFGS update to solve this problem along with backtracking line search. I am a novice in Matlab. Can anyone help, please? I can find a solution for a similar problem in that link: https://www.mathworks.com/help/optim/ug/unconstrained-nonlinear-optimization-algorithms.html .
But, I really don't know how to create a vector-valued function in Matlab (in my case input x can be an n-dimensional vector).
You will have to make quite a leap to get where you want to be -- may I suggest to go through some basic tutorial first in order to digest basic MATLAB syntax and concepts? Another useful read is the very basic example to unconstrained optimization in the documentation. However, the answer to your question touches only basic syntax, so we can go through it quickly nevertheless.
The absolute minimum to invoke the unconstraint nonlinear optimization algorithms of the Optimization Toolbox is the formulation of an objective function. That function is supposed to return the function value f of your function at any given point x, and in your case it reads
function f = objfun(x)
f = sum(100 * (x(2:end) - x(1:end-1).^2).^2 + (1 - x(1:end-1)).^2);
end
Notice that
we select the indiviual components of the x vector by matrix indexing, and that
the .^ notation effects that the operand is to be squared elementwise.
For simplicity, save this function to a file objfun.m in your current working directory, so that you have it available from the command window.
Now all you have to do is to call the appropriate optimization algorithm, say, the quasi Newton method, from the command window:
n = 10; % Use n variables
options = optimoptions(#fminunc,'Algorithm','quasi-newton'); % Use QM method
x0 = rand(n,1); % Random starting guess
[x,fval,exitflag] = fminunc(#objfun, x0, options); % Solve!
fprintf('Final objval=%.2e, exitflag=%d\n', fval, exitflag);
On my machine I see that the algorithm converges:
Local minimum found.
Optimization completed because the size of the gradient is less than
the default value of the optimality tolerance.
Final objval=5.57e-11, exitflag=1
I tried non-linear polynomial functions and this code works well. But for this one I tried several methods to solve the linear equation df0*X=f0 using backslash or bicg or lsqr, also tried several initial values but the result never converge.
% Define the given function
syms x1 x2 x3
x=[x1,x2,x3];
f(x)=[3*x1-cos(x2*x3)-1/2;x1^2+81*(x2+0.1)^2-sin(x3)+1.06;...
exp(-x1*x2)+20*x3+1/3*(10*pi-3)];
% Define the stopping criteria based on Nither or relative errors
tol=10^-5;
Niter=100;
df=jacobian(f,x);
x0=[0.1;0.1;-0.1];
% Setting starting values
error=1;
i=0;
% Start the Newton-Raphson Iteration
while(abs(error)>tol)
f0=eval(f(x0(1),x0(2),x0(3)));
df0=eval(df(x0(1),x0(2),x0(3)));
xnew=x0-df0\f0; % also tried lsqr(df0,f0),bicg(df0,f0)
error=norm(xnew-x0);
x0=xnew;
i=i+1
if i>=Niter
fprintf('Iteration times spill over Niter\n');
return;
end
end
You'll need anonymous functions here to better do the job (we mentioned it in passing today!).
First, let's get the function definition down. Anonymous functions are nice ways for you to call things in a manner similar to mathematical functions. For example,
f = #(x) x^2;
is a squaring function. To evaluate it, just write like you would on paper f(2) say. Since you have a multivariate function, you'll need to vectorize the definition as follows:
f(x) = #(x) [3*x(1) - cos(x(2) * x(3)) - 1/2; ...
For your Jacobian, you'll need to use another anonymous function (maybe call it grad_f) and compute it on paper, then code it in. The function jacobian uses finite differences and so the errors may pile up with the Jacobian is not stable in some regions.
The key is to just be careful and use some good coding practices. See this document for more info on anonymous functions and other good MATLAB practices.
I am trying to create an SDE model in Matlab with the sde function in the Econometrics toolbox. From looking at the examples on the website, the basic case seems simple enough in that an equation like
dX(t) = 0.1 X(t) dt + 0.3 X(t) dW(t)
can be defined by first creating anonymous functions and then using those in the SDE equation as seen below (where the variables used in the functions are previously defined):
F = #(t,X) 0.1 * X;
G = #(t,X) 0.3 * X;
obj = sde(F, G) % dX = F(t,X)dt + G(t,X)dW
I was hoping to do something just a bit more complicated in which the drift term of the SDE I would like to model is a function of another SDE. Specifically, the equation is
dY(t) / Y(t) = G(t) dt + sigma dW(t)
Where G(t) is another SDE I've already defined. Would someone be able to give me a sense of what the equation for the drift term (corresponding to F in the code above) would be in this case?
I don't have the Econometrics toolbox so I can't give you detailed code for it (most Matlab installs don't have this toolbox by default). However, your case is a pretty common so I imagine that it shouldn't be too hard to do what you need. You might consider creating a service request with The MathWorks or posting a question at Quant.StackExchange. Make sure you're clear about the SDEs that you're interested in. Sorry that I can't help you more in that area.
Another way to simulate this coupled set of SDEs is to use my own SDETools toolbox which is available for free on GitHub. These are quite straightforward if you have any experience with Matlab's ODE Suite functions such as ode45. SDETools also has dedicated functions for common stochastic process (e.g., geometric Brownian motion and Ornstein-Uhlenbeck) using their analytic solutions. Here is basic code with arbitrary parameter values to simulate your SDEs using the Euler-Maryama integrator function, sde_euler, in SDETools:
t0 = 0;
dt = 1e-2;
tf = 1e1;
tspan = t0:dt:tf; % Time vector
y0 = [1;1]; % Initial conditions
kappa = 10;
mu = 0;
tau = 1e-1;
sigma = 1e-2;
f = #(t,y)[kappa.*(mu-y(1));y(1).*y(2)]; % Drift
g = #(t,y)[tau;sigma.*y(2)]; % Diffusion
% Set random seed and type of stochastic integration
options = sdeset('RandSeed',1,'SDEType','Ito');
Y = sde_euler(f,g,tspan,y0,options); % Euler-Maruyama
figure;
plot(tspan,Y)
In fact, it's possible that the sde function in the Econometrics toolbox could itself take the two function handles, f and g, I created above.
Here's another way you can simulate the system (it may or may not be faster), this time using the sde_ou function to first generate an OU process, which itself is independent of the other equation:
...
options = sdeset('RandSeed',1);
Y(:,1) = sde_ou(kappa,mu,tau,tspan,y0(1),options); % OU process
f = #(t,y)Y(round(t/dt)+1,1).*y; % Index into OU process as a function of t
g = #(t,y)sigma.*y;
options = sdeset('RandSeed',2,'SDEType','Ito');
Y(:,2) = sde_euler(f,g,tspan,y0(2),options); % Euler-Maruyama of just second equation
figure;
plot(tspan,Y)
Note that even the the same random seed is used for the OU process, the output of Y(:,1) will be slightly different for this and the sde_euler case because of the order in which the Wiener increments are generated internally. Again, you may well be able to do something similar using the function in the Econometrics toolbox.
I'm trying to use ode45 to solve a system of ODE's:
[X,Y]= ode45(#sys,[0, T],y0);
where,
function dy = sys(t,y)
dy(1) = f_1(y)
dy(2) = f_2(y)
dy(3) = f_3(y)
end
The problem is that the function ode45 requires that y0 be initial values [y_1(0), y_2(0), y_3(0)], while in my system, I only have the values [y_2(0), y_3(0), y_3(T)] available.
Mathematically, this set of initial/terminal conditions should be enough to pin down the system, but is there any way I can work with that by ode45 or any other functions in MATLAB?
Thanks!
After digging in the Matlab documentation for a little bit, I think the more elegant way is to use the bvp4c function. bvp4c is a function specifically designed to handle boundary value problems like this, as opposed to ode**, which are really for initial value problems only. In fact, there's a whole set of other functions such as deval and bvpinit in Matlab that really facilitate the use of bvp4c. Here's the link to the Matlab documentation.
I'll post a brief (and perhaps a bit contrived) example here:
function [y1, y2, y3] = test(start,T)
solinit = bvpinit(linspace(0,3,10), [1,1,0]);
sol = bvp4c(#odefun,#bvpbc,solinit);
tspan = linspace(start,T,100);
S = deval(sol, tspan);
y1 = S(1,:);
y2 = S(2,:);
y3 = S(3,:);
plot (tspan,y1)
figure
plot (tspan,y2)
figure
plot (tspan,y3)
%% system definition & BVCs
function dydx = odefun(t,y)
dydx(1) = y(1) + y(2) + t;
dydx(2) = 2*y(1) + y(2);
dydx(3) = 3 * y(1) - y(2);
end
function res = bvpbc(y0,yT)
res= [y0(3) yT(2) yT(3)];
end
end
The test function outputs 3 vectors of solutions points for y1, y2 and y3 respectively, and also plots them.
Here are the variable paths plotted by Matlab:
Also, I found this video by professor Jake Blanchard from WMU to be very helpful.
One approach is to use the shooting method to iteratively solve for the unknown initial state y_1(0) such that the desired final state y_3(T) is satisfied.
The iteration proceeds by solving a nonlinear equation F = 0:
F(y_1(0)) = Y_3(T) - y_3(T)
where the uppercase function Y is the solution obtained by integrating the ODE's forward in time from a set of initial conditions. The task is to guess the value of y_1(0) to obtain F = 0.
Since we're now solving a nonlinear equation, all of the usual approaches apply. Specifically you could use either bisection or Newton's method to update your guess for the unknown initial state y_1(0). Note a couple of things:
The ODE's are integrated on [0,T] at each iteration of the nonlinear solve.
There may be multiple solutions for F = 0, depending on the structure of your ODE's.
Newton's method may converge faster than bisection, but may also be numerically unstable unless you can provide a good starting guess for y_1(0).
Using existing MATLAB functions, the bounded scalar nonlinear solver FMINBND might be a good choice as a nonlinear solver.
Hope this helps.
My Matlab program has multiple inputs as a struct (in.a, in.b, etc.)
and multiple outputs (out.a, out.b, etc.)
I would like to use the genetic algorithm solver from teh optimization toolbox to find the best input in.a, while all the other inputs are constant. The fitness is one of the outputs, e.g. out.b(2,3).
How do I "tell" the solver this?
Thanks
Daniel
It is not uncommon in programming to have a situation where what is most convenient for your function and what some library call expects of it don't agree. The normal resolution to such a problem is to write a small layer in between that allows the two to talk; an interface.
From help ga:
X = GA(FITNESSFCN,NVARS) finds a local unconstrained minimum X to the
FITNESSFCN using GA. [...] FITNESSFCN accepts a vector X of size
1-by-NVARS, and returns a scalar evaluated at X.
So, ga expects vector input, scalar output, whereas you have a structure going in and out. You would have to write the following (sub)function:
function Y = wrapper_Objfun(X, in)
in.a = X; %# variable being optimized
out = YOUR_REAL_FUNCTION(in); %# call to your actual function
Y = out.b(2,3); %# objective value
end
and then the call to ga will look like
X = ga(#(x) wrapper_Objfun(x,in), N);
where N is however large in.a should be.
Also have a read about it in Matlab's own documentation on the subject.