Solving ODEs with Matlab, with varying Parameters - matlab

Lets say I have a simple logistic equation
dx/dt = 2ax(1 - x/N)
where N is the carrying capacity, a is some growth rate, and both a and N are parameters I'd like to vary.
So what I want to do is to plot a 3D graph of my fixed point and the two parameters.
I understand how to find a fixed point of a single parameter.
Here is my sample code
function xprime = MyLogisticFunction(t,X) %% The ODE
% Parameters
N = 10 % Carrying Capacity
a = 0.5 % Growth Rate
x1prime = 2*a*X(1)*(1 - X(1)/N );
xprime = [x1prime ]';
end
Next my solver
% Initial Number
x0 = 0.4;
%Time Window
tspan=[0 100];
[t,x]=ode45(#MyLogisticFunction,tspan,x0);
clf
x(end,1) % This gives me the fixed point for the parameters above.
So my real question is, how do I put a for loop across two functions, that allows me to vary a and N, so that I can plot out a 3D graph of a and N and my fixed point x*.
I've tried combining both functions into one .m file but it does not seem to work

You need to pass the parameters to your function:
function xprime = MyLogisticFunction(t,X,a,N) %% The ODE
% Parameters (passed as function arguments)
% N = 10 % Carrying Capacity
% a = 0.5 % Growth Rate
x1prime = 2*a*X(1)*(1 - X(1)/N );
xprime = [x1prime ]';
end
and then when you call the ode solver:
% Initial Number
x0 = 0.4;
%Time Window
tspan=[0 100];
a = 0.1:0.1:1; % or whatever
N = 1:10; % or whatever
x_end = zeros(length(a),length(N));
for ii = 1:length(a)
for jj = 1:length(N)
[t,x]=ode45(#(t,X)MyLogisticFunction(t,X,a(ii),N(jj)),tspan,x0);
x_end(ii,jj) = x(end,1);
end
end

Related

Why is my decision boundary wrong for logistic regression using gradient descent?

I am trying to solve a classification task using logistic regression. Part of my task is to plot the decision boundary. I find that the gradient of the decision boundary seems to be solved correctly by my algorithm but when plotting the boundary is too high and does not separate the points well. I cannot work out why this is and would be grateful for any advice to solve this issue.
data = open('Question5.mat');
x = data.x; y = data.y; % Extract data for ease of use
LR = 0.001; % Set tunable learning rate for gradient descent
w_est = [0; 0; 0]; % Set inital guess for a, b, and c
cost = []; % Initalise array to hold value of cost function
figure;
for i = 1:20000 % Set iteration limit for gradient descent
iteration_cost = 0; grad_a = 0; grad_b = 0; grad_c = 0; % Set innial value of 0 for summed terms
for m = 1:1100 % Iterate through data points
y_hat_est = 1./(1+exp(-w_est'*[x(m,1); x(m,2); 1])); % Calculate value of sigmoid function with estimated coefficients for each datapoint
iteration_cost = iteration_cost + y(m)*log(y_hat_est)+(1-y(m))*log(1-y_hat_est); % Calculate cost function and add it to summed term for each data point
% Calculate each gradient term for each data point and add to
% summed gradient
grad_a = grad_a + (y_hat_est - y(m))*x(m,1);
grad_b = grad_b + (y_hat_est - y(m))*x(m,2);
grad_c = grad_c + (y_hat_est - y(m))*x(m,3);
end
g = [grad_a; grad_b; grad_c]; % Create vector of gradients
w_est = w_est - LR*g; % Update estimate vector with next term
cost(i) = -iteration_cost; % Add the value of the cost function to the array for costs
if mod(i,1000) == 0 % Only plot on some iterations to speed up program
hold off
gscatter(x(:,1),x(:,2),y,'rb'); % Plot scatter plot grouped by class
xlabel('x1'); ylabel('x2'); title(i); % Add title and labels to figure
hold on
x1_plot = -6:4; x2_plot = -3:7; % Create array of values for plotting
plot( -(w_est(1)*x1_plot + w_est(3)) /w_est(2), x2_plot); % Plot decision boundary based on the current coefficient estimates
% pause(1) % Add delay to aid visualisation
end
end
hold off;
figure; plot(cost) % Plot the cost function
title('Cost function'); xlabel('Iteration number'); ylabel('cost');
enter image description here

Why is my third MATLAB function outputing only zeros when using ode45?

I need to model negative, positive and simple regulation of a gene for my systems biology class using MATLAB. The problem is that the functions for negative and simple regulation work but the positive regulation function is only outputting zeros.
My script is as follows:
% Simulation of simple regulation, negative autoregulation and positive
% autoregulation
% Define constants
global a b K n
a = 1;
b = 1;
K = 0.5;
n = 2; % Hill coefficient
% Simulation time
tspan = [0,10];
% Initial condition
X0 = 0;
% Run simulations
[t1,X1] = ode45(#autoregulation_f0,tspan,X0); % Simple regulation
[t2,X2] = ode45(#autoregulation_f1,tspan,X0); % Negative autoregulation
[t3,X3] = ode23(#autoregulation_f2,tspan,X0); % Positive autoregulation
% Plot results
figure;
plot(t1,X1,t2,X2,t3,X3);
legend('simple','negative','Location','southeast');
And my functions are:
function dxdt = autoregulation_f0(t,X)
global a b
dxdt = b - a*X;
end
function dxdt = autoregulation_f1(t,X)
global a b K n
dxdt = b/(1+(X^n)/(K^n)) - a*X;
end
function dxdt = autoregulation_f2(t,X)
global a b K n
dxdt = b*X.^n./(K.^n+X.^n) + a*X;
end
The third function "autoregulation_f2(t,X)" is the one that outputs zeros and therefore when plotting the graph I just get a straight line.
Does anyone know what could be causing this?
Thanks in advance!
It looks to be the correct result for the given function. Your provided dxdt has an X in every term. The initial X0=0 will result in dxdt=0, giving you no change in X. As a result you just end up with a flat line.

MATLAB's lsim() vs for-loop Simulation // Different results for the same system

I've spent quite some time trying to simulate a simple SISO system using two approaches:
1) Using lsim() in MATLAB
2) By writing down the difference equations myself and iterate over them in a loop.
I was never able to get the same simulation results from both approaches, and I have no idea what I am doing wrong.
I stacked my code in a single m-file so it's easier to follow. Here is the code:
function main()
clear all
clc
simulateUsing_lsim()
simulateUsing_loop()
end
%%%%%% Simulating using lsim %%%%%%%
function simulateUsing_lsim()
% Define the continuous-time closed-loop system
P = getContPlant();
[Kp,Ki,Kd] = get_PIDgains();
C = pid(Kp,Ki,Kd);
clSys_cont = feedback(C*P,1);
% Define the discrete-time closed-loop system
hk = get_sampling_time();
clSys_disc = c2d(clSys_cont,hk);
% Generate the reference signal and the time vector
[r,t] = getReference(hk);
%% Simulate and plot using lsim
figure
lsim(clSys_disc,r,t)
%% Finding and plotting the error
y = lsim(clSys_disc,r);
e = r - y;
figure
p = plot(t,e,'b--');
set(p,'linewidth',2)
legend('error')
xlabel('Time (seconds)')
ylabel('error')
% xlim([-.1 10.1])
end
%%%%%% Simulating using loop iteration (difference equations) %%%%%%%
function simulateUsing_loop()
% Get the cont-time ol-sys
P = getContPlant();
% Get the sampling time
hk = get_sampling_time();
% Get the disc-time ol-sys in SS representation
P_disc = ss(c2d(P,hk));
Ad = P_disc.A;
Bd = P_disc.B;
Cd = P_disc.C;
% Get the PID gains
[Kp,Ki,Kd] = get_PIDgains();
% Generate the reference signal and the time vector
[r,t] = getReference(hk);
%% Perform the system simulation
x = [0 0]'; % Set initial states
e = 0; % Set initial errors
integral_sum = 0; % Set initial integral part value
for i=2:1:length(t)
% Calculate the output signal "y"
y(:,i) = Cd*x;
% Calculate the error "e"
e(:,i) = y(:,i) - r(i);
% Calculate the control signal vector "u"
integral_sum = integral_sum + Ki*hk*e(i);
u(:,i) = Kp*e(i) + integral_sum + (1/hk)*Kd*(e(:,i)-e(:,i-1));
% Saturation. Limit the value of u withing the range [-tol tol]
% tol = 100;
% if abs(u(:,i)) > tol
% u(:,i) = tol * abs(u(:,i))/u(:,i);
% else
% end
% Calculate the state vector "x"
x = Ad*x + Bd*u(:,i); % State transitions to time n
end
%% Subplots
figure
plot(t,y,'b',t,r,'g--')
%% Plotting the error
figure
p = plot(t,e,'r');
set(p,'linewidth',2)
legend('error')
xlabel('Time (seconds)')
ylabel('error')
end
function P = getContPlant()
s = tf('s');
P = 1/(s^2 + 10*s + 20);
end
function [Kp,Ki,Kd] = get_PIDgains()
Kp = 350;
Ki = 300;
Kd = 50;
end
function hk = get_sampling_time()
hk = 0.01;
end
function [r,t] = getReference(hk)
[r,t] = gensig('square',4,10,hk);
end
I got the plant model P and its PID controller from this page (see equation 10), where the system is simulated against a step reference and the result looks pretty much exactly like the lsim() result (just for a single step peak).
However, the result of simulating the system using lsim() is this:
whereas, using the for loop, I got this performance:
I would highly appreciate any help or clarification why I am getting different results.

How to debug this Matlab code to model glider descent?

I have this Matlab project but for some reason I just cannot stop thinking about it because I could not get it to work.
Objective:
This is a MATLAB script that would calculate the change of pressure, temperature and density of a glider that is being dropped from 10000 feet. As it falls, we want to use those new values calculated and then plugged in a function that has 4 equations that need to be differentiated at every point using ode45 as well as the new values of P T and Rho.
Here is the main code:
% HouseKeeping:
clc
clear all
close all
% Constants:
S = 232; % ft^2
Cd0 = 0.02;
K = 0.07;
W = 11000; % lbf
Cl_max = sqrt(Cd0/K);
Cd_max = 2*K*Cl_max^2;
Rho_10000 = .001756; % slugs/ ft^3
%Initial conditions:
t = 0; % Sec
x = 0; % ft
h = 10000; % ft
v = sqrt((2*W)/(Rho_10000*S*Cl_max)); %ft/s
gamma = -Cd_max/Cl_max;
% Find Endurance:
V_RD= sqrt((2*W)/(S* Rho_10000* sqrt(3*Cd0/K)));
RD= V_RD/((sqrt(3*Cd0/K))/(2*Cd0)) ; % ft/s
Endurcance= h/RD; % 958.3515 sec
% Sea Level values:
TSL = 518.69; % Rankine
PSL = 2116.199414; % lbs/ft^2
RhoSL = 0.0023769; % slugs/ft^3
while h > 0
tspan = [t t+1];
i=1;
X = [x;h;v;gamma;Rho_10000];
Time(i)= t;
% Calling ODE45:
[F] = ode45(# D,tspan, X)
% Hight Varying Parameters:
T = TSL - 0.00356616*h;
P = (1.137193514E-11)*(T)^5.2560613;
Rho = (RhoSL * TSL / PASL)*(P / T);
a = 49.0214 * (T)^.5;
H_Del(i) = (-Cd_max/Cl_max)*(plotted_x(i))+10000;
V_Del(i) = sqrt((2*W)/(Rho*S*Cl_max));
Gamma_Del(i) = -Cd_max/Cl_max;
i= i+1;
X = [ x ; H_Del(i); V_Del(i); Gamma_Del(i); Rho];
end
% Plots:
%1
figure (1)
plot(F(:,1),'-r',F(:,3),'-b')
title('Velocity vs Distance');
xlabel('x (ft)');
ylabel('v (ft/s)');
%2
Figure (2)
plot(F(:,1),'-r',F(:,2),'-b')
title('Altitude vs Distance ');
xlabel('x (ft)');
ylabel('h (ft)');
%3
figure (3)
plot(F(:,1),'-r',F(:,4),'-b')
title('Gamma vs Distance');
xlabel('x (ft)');
ylabel('Gamma (rad)');
%4
figure (4)
plot(t,'-r',F(:,3),'-b')
title('Velocity vs Time');
xlabel(' t (s)');
ylabel('v (ft/s)');
%5
figure (5)
plot(t,'-r',F(:,1),'-b')
title(' Distance vs Time ');
xlabel('t (s)');
ylabel('x (ft)');
%6
figure (6)
plot(t,'-r',F(:,4),'-b')
title('Gamma vs Time ');
xlabel('t (s)');
ylabel('Gamma (rad)');
%7
figure (7)
plot(t,'-r',F(:,3),'-b')
title('Velocity vs Time');
xlabel('t (s)');
ylabel('V (ft/s)');
Here is the Function
function [F] = D(X)
% Constants:
S = 232; % ft^2
Cd0 = 0.02;
K = 0.07;
W = 11000; % lbf
Cl_max = sqrt(Cd0/K);
Cd_max = 2*K*Cl_max^2;
Rho_10000 = .001756; % slugs/ ft^3
% Initial conditions:
t = 0; % Sec
x = 0; % ft
h = 10000; % ft
v = sqrt((2*W)/(Rho_10000*S*Cl_max)); % ft/s
gamma = -Cd_max/Cl_max;
g= 32.2; % ft/s^2
% Equations:
X_Pr = X(3)*cos(X(4));
H_Pr = X(3)*sin(X(4));
V_Pr = (-32.2./W)*(0.5*X(5)*Cd_max*S*X(3)^2 + W*sin(X(4)));
G_Pr = (32.2./(W*X(3)))*(0.5*X(5)*Cl_max*S*X(3)^2 - W*cos(X(4)));
F = [X_Pr;H_Pr;V_Pr;G_Pr];
I am not very good with Matlab but I did my very best! I went to my professors for help but they said they were too busy. I even stalked every senior I knew and they all said they did not know how to do it. My next project will be assigned soon and I think that if I cannot do this then I would not be able to do the next one.
Your code produces the following error:
Error using main>D
Too many input arguments.
This means that ode45 tries to call your provided function D with too many input arguments. You should check the desired odefun format in the ode45 documentation: dydt = odefun(t,y)
So, you should change your function declaration of D to
function [F] = D(t, X)
This should solve your first problem, but a following error pops up:
D returns a vector of length 4, but the length of initial conditions
vector is 5. The vector returned by D and the initial conditions
vector must have the same number of elements.
Again, you should check the ode45 documentation. Your function should return the derivatives of all your input variables X: F = dX/dt. You should also return the derivate of the fifth element Rho_10000.
Next, I got some error about undefined variables such as PASL. Probably because you did not post your full code.
Besides of the errors, you should really check your code again. You have written an infinite while loop while h > 0. You never change h in the loop, nor you use the output of ode45 in your loop. Furthermore you always overwrite your i and X value at the beginning of the loop, which is probably not what you want.
This is not a full answer to your question, but I hope you will be able to continue and post smaller, well defined problems, instead of one big problem which is very difficult to answer completely.

Plot step response without using step function

I want to plot the step response. I know that I can use step function with state space equations, but I try to get same results using plot function. Here is my sample of code:
for i=1:201
u(i) = 1;
x1(i+1) = (-(b/J)*x1(i) + (K/J)*x2(i));
x2(i+1) = (-(K/L)*x1(i) - (R/L)*x2(i) + (1/L)*u(i));
y(i) = x1(i);
end
and this is the state space equations:
A = [-b/J K/J
-K/L -R/L];
B = [0
1/L];
C = [1 0];
D = 0;
If i do:
t = 0:1:200;
plot(t, y)
it is not working and I want to have the same results like the step function below:
sys = ss(A,B,C,D);
step(sys)
You can find my state space equation here.
The reason for the mismatch is that sys is a continuous time model, whereas the computation of y treats it as a discrete-time system.
The following is a way of estimating the step-response of a continuous-time system in the discrete-time domain:
% Given from the problem statement
A = [-b/J K/J
-K/L -R/L];
B = [0
1/L];
C = [1 0];
D = 0;
% this is your continuous-time model
sys = ss(A,B,C,D);
% define the sample rate of the equivalent discrete-time model
Ts = 1/10;
% this needs to be something smaller than the time-constants in your model,
% so that you have enough resolution to represent the continuous-time
% signal.
% convert the system to the equivalent discrete-time model
sysd = c2d(sys,Ts);
% define how long a step response you'd like to compute
T = 7;
% this should be long enough to cover the length of the step response
t = 0:Ts:T; % time-grid for the plot
nSmp = length(t); % total number of samples to be computed
% initializations
y = NaN(1, nSmp); % output vector
u = ones(1, nSmp); % unit step input
X = [0; 0]; % state vector, initialized to 0
% compute the samples of the step-response
% (i prefer to use vectorized form to keep the code concise)
for i=1:nSmp
y(i) = sysd.C * X + sysd.D * u(i);
X = sysd.A * X + sysd.B * u(i);
end
% plot continous-time step response
figure;
step(sys);
% plot simulated discrete-time step response
figure;
plot(t, y, 'r')
xlabel('Time (s)');
ylabel('Amplitude');
title('Simulated Step Response');