How to solve two equations with bvp4c Matlab? - matlab

I need to solve two differential equations, where I have two boundary conditions for every equation. Because of that I choose Matlab method bvp4c to solve this system:
p1' = -32 * beta * m1 / (R ^ 4 * p1)
p2' = - ( - 8 * p1' / R - p1' * p2 - 32 * beta * m2 / R ^ 4 ) / p1
I have function file bvpfcn.m where I defined two differential equations:
function dpdz = bvpfcn(z,p)
beta = 1;
m1 = 1;
m2 = 0.1;
ri = 0.7;
z = linspace(0,1,1001);
R = ri - z .* (ri - 1);
dpdz = zeros(2,1001);
dpdz = [- 32 .* beta .* m0 ./ (R .^ 4 .* p(1));
-( - 8 .* dpdz(1) ./ R - dpdz(1) .* p(2) - 32 .* beta .* m1 ./ R .^ 4 ) ./ p(1);
];
end
Then in function file bcfcn.m I defined boundary conditions. My boundary conditions are:
p(1)|(z=0) = 8
p(1)|(z=1) = 1
p(2)|(z=0) = 0
p(2)|(z=1) = 0
And file bcfcn.m is:
function res = bcfcn(pa,pb)
res = [pa(1)-8;
pa(2);
pb(1)-1;
pb(2)];
end
My solution need to be of shape:
shape of expected solution
Because of that shape I am making guess function of cosine type:
function g = guess(z)
g = [0.65.*cos(z)
0.65.*cos(z)];
end
When I execute everything with:
beta = 1;
m1 = 1;
m2 = 0.1;
ri = 0.7;
xmesh = linspace(0,1,1001);
solinit = bvpinit(xmesh, #guess);
sol = bvp4c(#bvpfcn, #bcfcn, solinit);
I got error:
Error using bvparguments (line 111)
Error in calling BVP4C(ODEFUN,BCFUN,SOLINIT):
The boundary condition function BCFUN should return a column vector of length 2.
Error in bvp4c (line 130)
bvparguments(solver_name,ode,bc,solinit,options,varargin);
How can I make column vector when I have 4 boundary conditions? Are my assumpsions ok?

Your column vector from bvpfcn and bcfcn should have same dimensions. Since you have two first order ODEs, you should give only two boundary conditions. You have two extra boundary conditions, these extra conditions will be dependent on other two. You have to find out the independent boundary conditions

Related

MATLAB error using fzero function to solve the loop

My following code generates the plot of V and D values in figure 1. In the graph, the parabolas and straigh lines intersect, and I need to find the roots from the plot from a loop. So I tried to use fzero function, but the error appeared:
Operands to the logical AND (&&) and OR (||) operators must be convertible to logical scalar values. Use the ANY or ALL functions to reduce operands to logical scalar values.
Error in fzero (line 326)
elseif ~isfinite(fx) || ~isreal(fx)
Error in HW1 (line 35)
x=fzero(fun,1);
My code is:
clear all; close all
W = 10000; %[N]
S = 40; %[m^2]
AR = 7;
cd0 = 0.01;
k = 1 / pi / AR;
clalpha = 2*pi;
Tsl=800;
figure(1);hold on; xlabel('V');ylabel('D')
for h=0:1:8;
i=0;
for alpha = 1:0.25:12
i=i+1;
rho(i)=1.2*exp(-h/10.4);
cl(i) = clalpha * alpha * pi/180;
V(i) = sqrt(2*W/rho(i)/S/cl(i));
L(i) = 0.5 * rho(i) * V(i) * V(i) * S * cl(i);
cd(i) = cd0 + k * cl(i) * cl(i);
D(i) = 0.5 * rho(i) * V(i) * V(i) * S * cd(i);
clcd(i) = cl(i)/cd(i);
p(i) = D(i)*V(i);
ang(i) = alpha;
T(i)=Tsl*(rho(i)/1.2).^0.75;
end
figure(1); plot(V,D); hold on
plot(V,T);
end
fun = #(V) 0.5*V.*V.*rho.*S.*cd-T;
x=fzero(fun,1);
Probably, I should not use the fzero function, but the task is to find the roots of V from a plot (figure 1). There are parabolas and straight lines respectively.
From the documentation for fzero(fun,x)
fun: Function to solve, specified as a handle to a scalar-valued function or the name of such a function. fun accepts a scalar x and returns a scalar fun(x).
Your function does not return a scalar value for a scalar input, it always returns a vector which is not valid for a function which is being used with fzero.
1.- Your codes doesn't plot V and D: Your code plots D(V) and T(V)
2.- T is completely flat, despite taking part in the inner for loop calculations with T(i)=Tsl*(rho(i)/1.2).^0.75; as it had to be somehow modified.
But in fact it remains constant for all samples of V, constant temperature (°C ?), and for all laps of the outer for loop sweeping variable h within [0:1:8].
The produced T(V) functions are the flat lines.
3.- Then you try building a 3rd function f that you put as if f(V) only but in fact it's f(V,T) with the right hand side of the function with a numerical expression, without a symbolic expression, the symbolic expression that fzero expects to attempt zero solving.
In MATLAB Zero finding has to be done either symbolically or numerically.
A symbolic zero-finding function like fzero doesn't work with numerical expressions like the ones you have calculated throughout the 2 loops for h and for alpha .
Examples of function expressions solvable by fzero :
3.1.-
fun = #(x)sin(cosh(x));
x0 = 1;
options = optimset('PlotFcns',{#optimplotx,#optimplotfval});
x = fzero(fun,x0,options)
3.2.-
fun = #sin; % function
x0 = 3; % initial point
x = fzero(fun,x0)
3.3.- put the following 3 lines in a separate file, call this file f.m
function y = f(x)
y = x.^3 - 2*x - 5;
and solve
fun = #f; % function
x0 = 2; % initial point
z = fzero(fun,x0)
3.4.- fzeros can solve parametrically
myfun = #(x,c) cos(c*x); % parameterized function
c = 2; % parameter
fun = #(x) myfun(x,c); % function of x alone
x = fzero(fun,0.1)
4.- So since you have already done all the numerical calculations and no symbolic expression is supplied, it's reasonable to solve numerically, not symbolically.
To this purpose there's a really useful function called intersections.m written by Douglas Schwarz available here
clear all; close all;clc
W = 10000; %[N]
S = 40; %[m^2]
AR = 7;
cd0 = 0.01;
k = 1 / pi / AR;
clalpha = 2*pi;
Tsl=800;
figure(1);
ax1=gca
hold(ax1,'on');xlabel(ax1,'V');ylabel(ax1,'D');grid(ax1,'on');
title(ax1,'1st graph');
reczeros={}
for h=0:1:8;
i=0;
for alpha = 1:0.25:12
i=i+1;
rho(i)=1.2*exp(-h/10.4);
cl(i) = clalpha * alpha * pi/180;
V(i) = sqrt(2*W/rho(i)/S/cl(i));
L(i) = 0.5 * rho(i) * V(i) * V(i) * S * cl(i);
cd(i) = cd0 + k * cl(i) * cl(i);
D(i) = 0.5 * rho(i) * V(i) * V(i) * S * cd(i);
clcd(i) = cl(i)/cd(i);
p(i) = D(i)*V(i);
ang(i) = alpha;
T(i)=Tsl*(rho(i)/1.2).^0.75;
end
plot(ax1,V,D); hold(ax1,'on');
plot(ax1,V,T);
[x0,y0]=intersections(V,D,V,T,'robust');
reczeros=[reczeros [x0 y0]];
for k1=1:1:numel(x0)
plot(ax1,x0,y0,'r*');hold(ax1,'on')
end
end
Because at each pair D(V) T(V) there may be no roots, 1 root or more than 1 root, it makes sense to use a cell, reczeros, to store whatever roots obtained.
To read obtained roots in let's say laps 3 and 5:
reczeros{3}
=
55.8850 692.5504
reczeros{5}
=
23.3517 599.5325
55.8657 599.5325
5.- And now the 2nd graph, the function that is defined in a different way as done in the double for loop:
P = 0.5*V.*V.*rho.*S.*cd-T;
figure(2);
ax2=gca
hold(ax2,'on');xlabel(ax2,'V');ylabel(ax2,'P');grid(ax2,'on');
title(ax2,'2nd graph')
plot(ax2,V,P)
plot(ax2,V,T)
[x0,y0]=intersections(V,T,V,P,'robust');
for k1=1:1:numel(x0)
plot(ax2,x0,y0,'r*');hold(ax2,'on')
end
format short
V0=x0
P0=y0
V0 =
86.9993
P0 =
449.2990

The Fastest Method of Solving System of Non-linear Equations in MATLAB

Assume we have three equations:
eq1 = x1 + (x1 - x2) * t - X == 0;
eq2 = z1 + (z1 - z2) * t - Z == 0;
eq3 = ((X-x1)/a)^2 + ((Z-z1)/b)^2 - 1 == 0;
while six of known variables are:
a = 42 ;
b = 12 ;
x1 = 316190;
z1 = 234070;
x2 = 316190;
z2 = 234070;
So we are looking for three unknown variables that are:
X , Z and t
I wrote two method to solve it. But, since I need to run these code for 5.7 million data, it become really slow.
Method one (using "solve"):
tic
S = solve( eq1 , eq2 , eq3 , X , Z , t ,...
'ReturnConditions', true, 'Real', true);
toc
X = double(S.X(1))
Z = double(S.Z(1))
t = double(S.t(1))
results of method one:
X = 316190;
Z = 234060;
t = -2.9280;
Elapsed time is 0.770429 seconds.
Method two (using "fsolve"):
coeffs = [a,b,x1,x2,z1,z2]; % Known parameters
x0 = [ x2 ; z2 ; 1 ].'; % Initial values for iterations
f_d = #(x0) myfunc(x0,coeffs); % f_d considers x0 as variables
options = optimoptions('fsolve','Display','none');
tic
M = fsolve(f_d,x0,options);
toc
results of method two:
X = 316190; % X = M(1)
Z = 234060; % Z = M(2)
t = -2.9280; % t = M(3)
Elapsed time is 0.014 seconds.
Although, the second method is faster, but it still needs to be improved. Please let me know if you have a better solution for that. Thanks
* extra information:
if you are interested to know what those 3 equations are, the first two are equations of a line in 2D and the third equation is an ellipse equation. I need to find the intersection of the line with the ellipse. Obviously, we have two points as result. But, let's forget about the second answer for simplicity.
My suggestion it's to use the second approce,which it's the recommended by matlab for nonlinear equation system.
Declare a M-function
function Y=mysistem(X)
%X(1) = X
%X(2) = t
%X(3) = Z
a = 42 ;
b = 12 ;
x1 = 316190;
z1 = 234070;
x2 = 316190;
z2 = 234070;
Y(1,1) = x1 + (x1 - x2) * X(2) - X(1);
Y(2,1) = z1 + (z1 - z2) * X(2) - X(3);
Y(3,1) = ((X-x1)/a)^2 + ((Z-z1)/b)^2 - 1;
end
Then for solving use
x0 = [ x2 , z2 , 1 ];
M = fsolve(#mysistem,x0,options);
If you may want to reduce the default precision by changing StepTolerance (default 1e-6).
Also for more increare you may want to use the jacobian matrix for greater efficencies.
For more reference take a look in official documentation:
fsolve Nonlinear Equations with Analytic Jacobian
Basically giving the solver the Jacobian matrix of the system(and special options) you can increase method efficency.

expectation maximization algorithm matlab out of memory error

I am implementing Expectation Maximization algorithm in matlab. Algorithm is operating on 214096 x 2 data matrix and While computing probabilities, there is multiplication of ( 214096 x 2 ) * (2 x 2) * ( 2 x 214096 ) matrices, which is resulting in error of out of memory in matlab. Is there a way to fix this problem?
Equation
Matlab Code:
enter image description here D = size(X,2); % dimension
N = size(X,1); % number of samples
K = 4; % number of Gaussian Mixture components ( Also number of clusters )
% Initialization
p = [0.2, 0.3, 0.2, 0.3]; % arbitrary pi, probabilities of clusters, apriori probability of cluster
[idx,mu] = kmeans(X,K); % initial means of the components, theta is mu and variance
% compute the covariance of the components
sigma = zeros(D,D,K);
for k = 1:K
tempmat = X(idx==k,:);
sigma(:,:,k) = cov(tempmat); % Sigma j
sigma_det(k) = det(sigma(:,:,k));
end
% calculate x-mu
for k=1: K
check=length( X(idx == k,1))
for lidx = 1: length( X(idx == k,1))
cidx = find( idx == k) ;
Xmu(cidx(lidx),:) = X(cidx(lidx),:) - mu(k,:); %( x-mu ) calculation on cluster level
end
end
% compute P(Cj|x; theta(t)), and take log to simplified calculation
%Eq 14.14 denominator
denom = 0;
for k=1:K
calc_sigma_1_2 = sigma_det(k)^(-1/2);
calc_x_mu = Xmu(idx == k,:);
calc_sigma_inv = inv(sigma(:,:,k));
calc_x_mu_tran = calc_x_mu.';
factor = calc_sigma_1_2 * exp (-1/2 * calc_x_mu * calc_sigma_inv * calc_x_mu_tran ) * p(k);
denom = denom + factor;
end
for k =1:K
calc_sigma_1_2 = sigma_det(k)^(-1/2);
calc_x_mu = Xmu(idx == k,:);
calc_sigma_inv = inv(sigma(:,:,k));
calc_x_mu_tran = calc_x_mu.';
factor = calc_sigma_1_2 * exp (-1/2 * calc_x_mu_tran * calc_sigma_inv * calc_x_mu ) * p(k);
pdf(k) = factor/denom;
end
%%%% Equation 14.14 ends
It seems that you tried to apply vector based equation by simply substituting vector for matrix, this is not how it works
(x - mu).' * Inv(sigma) * (x-mu)
is supposed to be mahalanobis norm of (x-mu), and you want to obtain this value per each row of matrix X, thus
(X - mu).' * Inv(sigma) =: A <- this is ok, this results in N x d matrix
and now you have to do point-wise multiplication of A with (X - mu), not a dot product, and finally sum over second axis (columns), this way you end up with N element vector, each containing a mahalanobis norm of corresponding row from X.

Optimization with Lagrange multipliers

I have an optimization problem which I have to solve using Lagrange multipliers.
I have the following code:
clear all
clc
p = #(r,sig) (r./sig.^2) .* exp(-r.^2/2*(sig.^2));
sig = 1;
Pa = 1;
Pc = 20;
a = 0.5;
b = 1;
phi = #(h_AB,h_AC,h_CB) abs(h_AB).^2 +((b .* a.^2*abs(h_AC).^2 .* abs(h_CB).^2)
.* Pc ./ (1 + b * a .^2 .* abs(h_CB) .^2 * Pc));
f1 = #(h_AB,h_AC,h_CB) .5*log((1+phi(h_AB,h_AC,h_CB)*Pa)/(1+abs(h_AC).^2*Pa));
f2 = #(h_AB,h_AC,h_CB) f1(h_AB,h_AC,h_CB) .* p(h_AB,sig) .* p(h_AC,sig).* (h_CB,sig);
q = integral3(f2,-inf,inf,-inf,inf,-inf,inf);
The constant b that I have defined should be a variable (q be a function of b), so that I would find e = jacobian(q,[b]); in the next step.
The problem is that I can't define b as symbolic while other functions are not symbolic and when I define all the functions in symbolic form, I get out of memory solving e = jacobian(q,[b]);

Octave backpropagation implementation issues

I wrote a code to implement steepest descent backpropagation with which I am having issues. I am using the Machine CPU dataset and have scaled the inputs and outputs into range [0 1]
The codes in matlab/octave is as follows:
steepest descent backpropagation
%SGD = Steepest Gradient Decent
function weights = nnSGDTrain (X, y, nhid_units, gamma, max_epoch, X_test, y_test)
iput_units = columns (X);
oput_units = columns (y);
n = rows (X);
W2 = rand (nhid_units + 1, oput_units);
W1 = rand (iput_units + 1, nhid_units);
train_rmse = zeros (1, max_epoch);
test_rmse = zeros (1, max_epoch);
for (epoch = 1:max_epoch)
delW2 = zeros (nhid_units + 1, oput_units)';
delW1 = zeros (iput_units + 1, nhid_units)';
for (i = 1:rows(X))
o1 = sigmoid ([X(i,:), 1] * W1); %1xn+1 * n+1xk = 1xk
o2 = sigmoid ([o1, 1] * W2); %1xk+1 * k+1xm = 1xm
D2 = o2 .* (1 - o2);
D1 = o1 .* (1 - o1);
e = (y_test(i,:) - o2)';
delta2 = diag (D2) * e; %mxm * mx1 = mx1
delta1 = diag (D1) * W2(1:(end-1),:) * delta2; %kxm * mx1 = kx1
delW2 = delW2 + (delta2 * [o1 1]); %mx1 * 1xk+1 = mxk+1 %already transposed
delW1 = delW1 + (delta1 * [X(i, :) 1]); %kx1 * 1xn+1 = k*n+1 %already transposed
end
delW2 = gamma .* delW2 ./ n;
delW1 = gamma .* delW1 ./ n;
W2 = W2 + delW2';
W1 = W1 + delW1';
[dummy train_rmse(epoch)] = nnPredict (X, y, nhid_units, [W1(:);W2(:)]);
[dummy test_rmse(epoch)] = nnPredict (X_test, y_test, nhid_units, [W1(:);W2(:)]);
printf ('Epoch: %d\tTrain Error: %f\tTest Error: %f\n', epoch, train_rmse(epoch), test_rmse(epoch));
fflush (stdout);
end
weights = [W1(:);W2(:)];
% plot (1:max_epoch, test_rmse, 1);
% hold on;
plot (1:max_epoch, train_rmse(1:end), 2);
% hold off;
end
predict
%Now SFNN Only
function [o1 rmse] = nnPredict (X, y, nhid_units, weights)
iput_units = columns (X);
oput_units = columns (y);
n = rows (X);
W1 = reshape (weights(1:((iput_units + 1) * nhid_units),1), iput_units + 1, nhid_units);
W2 = reshape (weights((((iput_units + 1) * nhid_units) + 1):end,1), nhid_units + 1, oput_units);
o1 = sigmoid ([X ones(n,1)] * W1); %nxiput_units+1 * iput_units+1xnhid_units = nxnhid_units
o2 = sigmoid ([o1 ones(n,1)] * W2); %nxnhid_units+1 * nhid_units+1xoput_units = nxoput_units
rmse = RMSE (y, o2);
end
RMSE function
function rmse = RMSE (a1, a2)
rmse = sqrt (sum (sum ((a1 - a2).^2))/rows(a1));
end
I have also trained the same dataset using the R RSNNS package mlp and the RMSE for train set (first 100 examples) are around 0.03 . But in my implementation I cannot achieve lower RMSE than 0.14 . And sometimes the errors grow for some higher learning rates, and no learning rate gets me lower RMSE than 0.14. Also a paper i referred report the RMSE in for the train set is around 0.03
I wanted to know where is the problem i the code. I have followed Raul Rojas book and confirmed that things are okay.
In backprobagation code the line
e = (y_test(i,:) - o2)';
is not correct, because the o2 is the output from the train set and i am finding the difference from one example from the test set y_test. The line should have been as below:
e = (y(i,:) - o2)';
which correctly finds the difference between the predicted output by the current model and the target output of the corresponding example.
This took me 3 days to find this one, I am fortunate enough to find this freaking bug which stopped me from going into further modifications.