I am trying to replicate the results of a paper (Immune Response). In short, it looks at the concentration of pathogens, antibodies and plasma cells, and the effect the immune response has on an organ. Depending on the state of the organ, a variable which affects the concentration of plasma cells will change.
I have modeled this in Matlab. My issue is that the conditional statements for the plasma-concentration-affecting variable is being ignored. By commenting out portions of the code and looking at the graphs, regardless of what the second condition is, the output is only responding to the initial condition.
How can I update values so that they are interpreted by ode45 (or ode23) and is there a better approach to approach this problem?
My code is below.
function dx = iir_2(t, x)
dx = [0; 0; 0; 0];
a11 = 1;
a31 = 1;
a41 = 1;
a12 = 1;
a22 = 3;
a32 = 1.5;
a42 = 1;
a23 = 1;
a33 = 0.5;
b1 = -1;
b2 = 1;
b3 = 1;
b4 = -1;
u1 = 0;
u2 = 0;
u3 = 0;
u4 = 0;
tau = 0.1;
if x(4) >= 0.5
a21x4 = 0;
else
a21x4 = cos(pi * x(4));
end
if x(4) > 1
x(4) = 1;
end
dx(1) = (a11 - a12 * x(3)) * x(1) + b1 * u1;
dx(2) = a21x4 * a22 * x(1) * (t - tau) * x(3) * (t - tau) - a23 * (x(2) - 2) + b2 * u2;
dx(3) = a31 * x(2) - (a32 + a33 * x(1)) * x(3) + b3 * u3;
dx(4) = a41 * x(1) - a42 * x(4) + b4 * u4;
This second script that calls the above function is..
Case = ['Subclinical' 'Clinical' 'Chronic' 'Lethal'];
x1_0 = [1.5 2 2.57 3];
x2_0 = 2;
x3_0 = (1*x2_0)/1.5;
x4_0 = 0;
for i = 1:4
if i == 1
state = 'Subclinical';
elseif i == 2
state = 'Clinical';
elseif i == 3
state = 'Chronic';
else
state = 'Lethal';
end
options = odeset('RelTol', 1e-3, 'NonNegative', [1 2 3 4]);
[t,x] = ode45(#iir_2, [0 10], [x1_0(i) x2_0 x3_0 x4_0], options); % use ode23???
figure
plot(t,x);
str = sprintf('Case Number = %d\nx(0) = %d\n%s', i, x1_0(i), state);
title(str);
axis([0,10,0,10])
legend('Pathogen', 'Plasma Cell', 'Antibody', 'Organ');
end
The conditional statements are in the function.
if x(4) >= 0.5
a21x4 = 0;
else
a21x4 = cos(pi * x(4));
end
if x(4) > 1
x(4) = 1;
end
There are two ways of doing this.
Either way you need to understand that you cannot just set x(4) to 1 and hope everything works out for the best. Matlab won't care about the preceding values of x(4) as they are all stored in memory. Furthermore, the upcoming value of x(4) is determined by dx(4) and the previously retained values of x(4) (which you cannot set).
You have two possible solutions to your problem:
A) set dx(4) = 0 when your condition is met
if x(4) > 1
dx(4) = 0;
else
dx(4) = a41 * x(1) - a42 * x(4) + b4 * u4;
end
This however will not result in a perfect x(4) = 1, rather there will be a small error.
B) Calling an event function, which can be learned about here and here, in which case you can interrupt for a new function call.
Related
T = 0.2;
A = [1 T; 0 1];
B = [T^2 / 2 T];
H = [1 0];
G = [0 1]';
Q = 0.00005;
R = 0.006;
x1(1) = 0;
x2(1) = 0;
x1e(1) = 0;
x2e(1) = 0;
xest = [x1e(1) x2e(1)]';
x1p(1) = 0;
x2p(1) = 0;
PE = [R 0; 0 0];
PP = A * PE(1) * A' + Q;
for i= 1:25
if i < 10
u = 0.25;
else
u = 0;
end
x1(i+1) = x1(i) + T * x2(i) + (T^2 / 2) * u;
x2(i+1) = x2(i) + T * u + sqrt(Q) * randn;
y(i+1) = x1(i+1) + sqrt(R) * randn;
PP = A * PE * A' + G * Q * G';
K = PP * H' * inv(H * PP * H' + R);
PE = [eye(2) - K * H] * PP;
xpredict = A * xest + B * u;
xest = xpredict + K * (y(i+1) -H * xpredict);
x1e(i+1) = [1 0] * xest;
x2e(i+1) = [0 1] * xest;
end
Unable to perform assignment because the left and right sides have a different number of elements.
Error in rrrr (line 34)
x1e(i+1) = [1 0] * xest;
how i can solve the error
xpredict must be a 2x1 vector. To solve it, you need to transpose B in line 5 i.e., B = [T^2 / 2 T]',
Since from Newton's laws of motion with constant velocity, we have
I am using following objective function for optimization:
function Length_Sum = objective_function( l1,l2,l3 )
Length_Sum = l1 + l2 + l3;
end
With constraints function given below, the constrint function uses another function for calculating values of thetas,
function [c, ceq] = simple_constraint(l1,l2,l3)
c(1) = l3^2 + 200*l3*cos(30) + 10000 - (l1 + l2)^2;
c(2) = (100- l3*cos(30))^2 + (100*sin(30))^2 - (l1-l2)^2;
thetas = inverse_kinematics(l1,l2,l3);
c(3) = thetas(4,1) - 160;
c(4) = thetas(4,2) - 160;
c(5) = thetas(4,3) - 160;
c(6) = 20 - thetas(4,1);
c(7) = 20 - thetas(4,2);
c(8) = 20 - thetas(4,3);
c(9) = thetas(5,1) - 340;
c(10) = thetas(5,2) - 340;
c(11) = thetas(5,3) - 340;
c(12) = 200 - thetas(5,1);
c(13) = 200 - thetas(5,2);
c(14) = 200 - thetas(5,3);
c(15) = thetas(6,1) - 340;
c(16) = thetas(6,2) - 340;
c(17) = thetas(6,3) - 340;
c(18) = 200 - thetas(6,1);
c(19) = 200 - thetas(6,2);
c(20) = 200 - thetas(6,3);
ceq = [];
end
Function called by constraint function is given below,
function thetas = inverse_kinematics(l1,l2,l3)
x = 100;
y = 0;
phi = 210*pi/180:60*pi/180:330*pi/180;
x1 = x - (l3*cos(phi));
y1 = y - (l3*sin(phi));
a = sqrt(x1.^2 + y1.^2);
y2 = -y1./a;
x2 = -x1./a;
gamma = atan2(y2,x2);
c = (- x1.^2 - y1.^2 - l1^2 + l2^2)./(2*l1*a);
d = acos(c);
theta1 = gamma + d;
if theta1 < 0
theta1 = theta1 + 2*pi;
end
theta4 = gamma - d;
if theta4 < 0
theta4 = theta4 + 2*pi;
end
e = (y1 - l1*sin(theta1))/l2;
f = (x1 - l1*cos(theta1))/l2;
theta2 = atan2(e,f) - theta1;
if theta2 < 0
theta2 = theta2 + 2*pi;
end
g = (y1 - l1*sin(theta4))/l2;
h = (x1 - l1*cos(theta4))/l2;
theta5 = atan2(g,h) - theta4;
if theta5 < 0
theta5 = theta5 + 2*pi;
end
theta3 = (phi)- (theta1 + theta2);
if theta3 < 0
theta3 = theta3 + 2*pi;
end
theta6 = (phi)- (theta4 + theta5);
if theta6 < 0
theta6 = theta6 + 2*pi;
end
thetas = [theta1;theta2;theta3;theta4;theta5;theta6].*180/pi;
end
After running this code using ga toolbox, with lower bounds [20 20 20] and upper bounds [100 100 100] and rest parameters set to default, I am getting "Error in running optimization. Not enough input arguments" error. Can someone help?
ga accepts constraint function with input in form of one vector with number of elements corresponding to number of constrainded variables. You should change
function [c, ceq] = simple_constraint(l1,l2,l3)
to
function [c, ceq] = simple_constraint(input)
l1 = input(1);
l2 = input(2);
l3 = input(3);
Next time, I suggest you try File->Generate Code... option from the mentioned toolbox. Then you can debug more easily from Matlab window.
There is also another problem in your program. Try running inverse_kinematics(20,20,20). It fails on line 29, but I won't go into details here, because this is not part of the question.
I am trying to create a program to solve a moment methods for a polymer reaction. However, when im run the code this error appears "Too many Input Arguments", any help? (sorry for bad english)
Code:
First function
function dydt = osc(t,y)
ka1 = 10^6;
ka2 = 0.15*10^6;
kp = 2952;
kd = 0.106*2952;
ks = 10^6;
%y=[C,A,ROH,I,M,Lambda,Mi] <=> y(1,:)=[C] ; y(2,:)=[A]
% y(3,:)=[ROH] ; y(4,:)=[I]
% y(5,:)=[M] ;
% y(6-8,:)=[Lambda] onde: %y(6) - lambda0 ;
y(7) - lambda1 ; y(8) - lambda2
% y(9-11,:)=[Mi] onde: %y(9) - mi0 ; y(10) -
mi1 ; y(11) - mi2
% y(12,:)=[R1] ; y(13;:) = [D1]
j = 10;
syms n
%Variables
dydt(1,1) = - ka1*y(1)*y(3) + ka2*y(4)*y(2) - ka1*y(1)
dydt(2,1) = + ka1*y(1)*y(3) - ka2*y(4)*y(2) + ka1*y(1)
dydt(3,1) = - ka1*y(1)*y(3) + ka2*y(4)*y(2) - ks*y(3)*
dydt(4,1) = - kp*y(5)*y(4) + kd*y(12) + ka1*y(1)*y(3) - ka2*y(4)*y(2)
%Living Chains
dydt(6,1) = + ka1*y(1)*symsum((n^0)*y(9), n, [1 j])
dydt(7,1) = + ka1*y(1)*symsum((n^1)*y(10), n, [1 j])
dydt(8,1) = + ka1*y(1)*symsum((n^2)*y(11), n, [1 j])
%Dormant Chains
dydt(9,1) = - ka1*y(1)*symsum((n^0)*y(9), n, [1 j])
dydt(10,1) = - ka1*y(1)*symsum((n^1)*y(10), n, [1 j]) +
dydt(11,1) = - ka1*y(1)*symsum((n^2)*y(11), n, [1 j])
%R1 e D1
dydt(12,1) = + kp*y(5)*y(4) - kp*y(5)*y(12) + kd*((y(12)+1) - y(12))
dydt(13,1) = - ka1*y(1)*y(13) + ka2*y(2)*y(13) + ks*y(3)*y(12)
end
Second function
function [t,y]= call_osc()
%Tempo
tspan = [0 1];
%Initial conditions
C = 2.582;
A = 3.9*10^3;
ROH = 0.387*10^2;
I = 10^3;
M = 1460.495;
Rn0 = 0;
Rn1 = 0;
Rn2 = 0;
Dn0 = 0;
Dn1 = 0;
Dn2 = 0;
R1 = 1;
D1 = 1;
y0 = [C; A; ROH; I; M; Rn0; Rn1; Rn2; Dn0; Dn1; Dn2; R1; D1];
[t,y] = ode15s(#osc, tspan, y0);
disp(y(:,1))
end
I am right now stuck on a problem in matlab. What I have done is that I have an equation that is passed on into another function which works by the bisection-method.
But I have a multiplier that I am trying to implement which somehow leads to the function crashing.
Before I introduced the multiplier it all worked, I tried breaking it down by entering the multiplier value manually and it didn't work
P_{1} = 0.6;
P_{2} = 0.2;
P_{3} = 0.2;
a_1 = 4/3;
a_2 = -7/3;
b_1 = -1/3;
b_2 = 4/3;
persistent multiplier
multiplier = exp(a_1 * 44 + a_2 * 14 + 0);
eqn = #(x) ((a_1 * x + b_1)^a_1) * ((a_2 * x + b_2)^a_2) * x ...
-(P_{1}^a_1) * (P_{2}^a_2) * P_{3} * multiplier;
Q_{3} = Bisectionmethod(a_1, a_2, b_1, b_2, eqn);
Here is the calculating part of the bisection method.
x_lower = max(0, -b_1 / a_1);
x_upper = -b_2 / a_2;
x_mid = (x_lower + x_upper)/2;
Conditional statement encompassing the method of bisection
while abs(eqn(x_mid)) > 10^(-10)
if (eqn(x_mid) * eqn(x_upper)) < 0
x_lower = x_mid;
else
x_upper = x_mid;
end
x_mid = (x_lower + x_upper)/2;
end
Based on the information you provided this is what I came up with
function Q = Stackoverflow
persistent multiplier
P{1} = 0.6;
P{2} = 0.2;
P{3} = 0.2;
a1 = 4/3;
a2 = -7/3;
b1 = -1/3;
b2 = 4/3;
multiplier = exp(a1 * 44 + a2 * 14 + 0);
eqn = #(x) ((a1 .* x + b1).^a1) .* ((a2 .* x + b2).^a2) .* x -(P{1}.^a1) .* (P{2}.^a2) .* P{3} .* multiplier;
Q{3} = Bisectionmethod(eqn, max([0, -b1/a1]), -b2/a2, 1E-10);
end
function XOut = Bisectionmethod(f, xL, xH, EPS)
if sign(f(xL)) == sign(f(xH))
XOut = [];
error('Cannot bisect interval because can''t ensure the function crosses 0.')
end
x = [xL, xH];
while abs(diff(x)) > EPS
x(sign(f(mean(x))) == sign(f(x))) = mean(x);
end
XOut = mean(x);
end
I am currently trying to run experiments in parallel using MATLAB 2011b that are very time-consuming.
I am wondering if someone could help me 'translate' the following block of generic (non-working) parfor code into something that will work in the spmd code.
amountOfOptions = 8;
startStockPrice = 60 + 40 * rand(1,amountOfOptions);
strike = 70 + 20 * rand(1,amountOfOptions);
v = 0.35 + 0.3 * rand(1,amountOfOptions);
IV = 0.25 + 0.1 * rand(1,amountOfOptions);
sigma = 0.15 + 0.65 * rand(1,amountOfOptions);
riskFreeRate = 0.05 + 0.1 * rand(1,amountOfOptions);
tn = fix(1 + 3 * rand(1,amountOfOptions));
tic;
for g=1:amountOfOptions
for i=1:10
N = i*5;
Cti = zeros(1,N);
Sti = zeros(1,N);
B = zeros(1,N);
d1_ti = zeros(1,N);
delta_t = zeros(1,N);
ctn = 0;
cmtn = 0;
result = 0;
t = (1:N)/N;
dt = 1/N;
c_mt0 = 0;
for j=1:10
B = sigma(g)*randn(1,N);
part1 = startStockPrice(g)*normcdf((log(startStockPrice(g)/strike(g))+(riskFreeRate(g)+(0.5*(IV(g))^2))*(tn))/(v(g)*sqrt(tn)),0,sigma(g));
part2 = exp(-riskFreeRate(g)*tn)*strike(g)*normcdf((log(startStockPrice(g)/strike(g))+(riskFreeRate(g)-(0.5*(IV(g))^2))*(tn))/(IV(g)*sqrt(tn)));
c_mt0 = part1 - part2;
Sti(1) = startStockPrice(g);
for j = 2:N-1
Sti(j)=Sti(j-1)*exp( (riskFreeRate(g)-dt*0.5*sigma(g)^2) * t(j)*dt + sigma(g)*B(j));
end
Sti(N) = Sti(N-1)*exp( (riskFreeRate(g)-dt*0.5*sigma(g)^2) * t(N)*dt + sigma(g)*B(N));
parfor i = 1:N-1
d1ti(i) = (log(Sti(i)/strike(g)) + (riskFreeRate(g) + v(g).^2/2) * (tn - t(i))) / (v(g) * sqrt(tn - t(i)));
end
parfor i = 1:N-1
Cti(i) = Sti(i).*normcdf((d1ti(i)),0,sigma(g)) - exp(-riskFreeRate(g).*(tn(g) - t(i))).*strike(g).*normcdf(((d1ti(i) - v(g)*sqrt(tn(g) - t(i)))) , 0 ,sigma(g));
end
if((Sti(N) - strike(g)) > 0)
ctn = Sti(N) - strike(g);
else
ctn = 0;
end
parfor i = 1:N-1
delta_t(i) = normcdf((d1ti(i)),0,sigma(g));
end
cmtn = ctn - c_mt0*exp(riskFreeRate(g)*tn(g));
result= cmtn + result;
end
result= result/10;
end
end
time = toc;
I've always used parfor over spmd because it's more logical for me. Since parfor requires that each iteration within the loop be independent of all other iterations. It's as easy as encapsulating it using the following method.
% Initial Variables
amountOfOptions = 8;
startStockPrice = 60 + 40 * rand(1,amountOfOptions);
strike = 70 + 20 * rand(1,amountOfOptions);
v = 0.35 + 0.3 * rand(1,amountOfOptions);
IV = 0.25 + 0.1 * rand(1,amountOfOptions);
sigma = 0.15 + 0.65 * rand(1,amountOfOptions);
riskFreeRate = 0.05 + 0.1 * rand(1,amountOfOptions);
tn = fix(1 + 3 * rand(1,amountOfOptions));
% Open Parpool
try
parpool;
catch
end
% Use parfor
parfor i = 1:amountOfOptions
[startStockPrice(i),strike(i),v(i),IV(i),sigma(i),riskFreeRate(i),tn(i)] = fun( startStockPrice(i),strike(i),v(i),IV(i),sigma(i),riskFreeRate(i),tn(i) );
end
Then you can create the encapsulating function fun that will accept all the parameters and process/reoutput them. It will have the following definition/header:
function [startStockPrice,strike,v,IV,sigma,riskFreeRate,tn] = fun( startStockPrice,strike,v,IV,sigma,riskFreeRate,tn );