MATLAB: Residual error in Cramer's rule - matlab

I am quite familiar with Cramer's rule and I know why it is "useless". However, I got curious when the residual using the code below gives something like xxxxE-016 where xxxx represent numbers. I have tried the code below with 3 to 10 matrix sizes of floating system of linear equation.
Why is the residual error minimal?
Am I missing the right syntax for disp(['norm of Cramer's rule residual = ' num2str(norm(A*x-b),4)]) in the code for getting such minimal error?
The code I provided is working perfectly, only doubting the syntax I used for the norm
function x=cramerr(A,b)
A=input('matrix A =');
b=input('vector b =');
n=size(A,1);
m=size(A,2);
tic;
if n~=m
Error ('The matrix is not square!');
x=[];
else
detA=det(A);
if det(A)~=0
x=zeros(n,1);
for j=1:n
if j~=1 & j~=n
Ab=[A(:,1:j-1) b A(:,j+1:n)];
elseif j==1
Ab=[b A(:,2:n)];
elseif j==n
Ab=[A(:,1:n-1) b];
end
x(j)=det(Ab)/detA;
end %for j=1:n
else
Error('The matrix A has a zero determinant');
x=[];
end % if det(A)~=0
toc;
disp(['norm of Cramer's rule residual = ' num2str(norm(A*x-b),4)]);
end % if n~=m
Please you can use this as an example
A =[0.373,0.296;0.326,0.260];
b =[0.521;0.456];
Thanks

I wouldn't say this is a problem per se. What you do when you use Cramer's rule is solve the linear system of equations. In Matlab, you can simply do that with x=inv(A)*b, which uses a different algorithm to calculate the inverse (LU decomposition). In the Matlab page on Inverses and Determinants it says:
If A is square and nonsingular, the equations AX = I and XA = I have
the same solution, X. This solution is called the inverse of A, is
denoted by A-1, and is computed by the function inv. The determinant
of a matrix is useful in theoretical considerations and some types of
symbolic computation, but its scaling and round-off error properties
make it far less satisfactory for numeric computation. Nevertheless,
the function det computes the determinant of a square matrix.
If you want to check the precision of both you could do this:
format long
built_in=inv(A)*b
own_function=r(A,b)
and compare the results. What I got was:
built_in= [1.000000000000000;0.500000000000000]
own_function= [1.000000000000054;0.500000000000000]
You can see where the small norm comes from. With this in mind such an error is most likely due to rounding off errors.
As for the formatting of disp(['norm of Cramer's rule residual = ' num2str(norm(A*x-b),4)]) I would skip the apostrophe (') in Cramer's as this will cause errors.

Related

Simple script that computes a solution of linear ODEs giving wrong result

this a question that envolves both programming and mathematics. So, I'm trying to write a code that computes the general solution of a system of linear ODEs described by . The mathematical formula it's shown above:
where the greek symbol \PHI that appers in the equation is the expm(A*t)
clear all
A=[-2]; %system matrix
t0=1; %initial time of simulation
tf=2; %final time of simulation
syms t x_0
x0=x_0;
hom=expm(A*t); %hom means "homogeneous solution"
hom_initialcond=hom*x0;%this is the homogeneous solution multiplied by the initial conditon
invhom=inv(hom); %this is the inverse of the greek letter at which, multiplied by the input of the system, composes the integrand of the integral
g=5*cos(2*t); %system input
integrand=invhom*g; %computation of the integrand
integral=int(integrand,t0,t); %computation of the definite integral from t0 to t, as shown by the math formula
partsol=hom*integral; %this is the particular solution
gen_sol=partsol+hom_initialcond %this is the general solution
x_0=1; %this is the initial condition
t=linspace(t0,tf); %vector of time from t0 to tf
y=double(subs(gen_sol)); %here I am evaluating my symbolic expression
plot(t,y)
The problem is that my plot of the ODE's solution it's not looking well, as you can see:
The solution it's wrong because the curve shown in the graph doesnt start at the initial value equals 1. But the shape it's very similar from the plot gave by the MATLAB ODE solver:
However, if I set t0=0 then the plot gave by my code and by MATLAB solver it's exacly equal to each other. So, my code it's fine for t0=0 but with any other values my code goes wrong.
The general solution in terms of fundamental matrices is
or more often seen as
But since the initial time is often taken to be zero, the inverse of the fundamental matrix is often omitted since it is the identity for linear, constant coefficient problems at zero (i.e., expm(zeros(n)) == eye(n)) and the c vector is equivalent to the initial condition vector.
Swapping some of the lines around near your symbolic declaration to this
syms t x_0 c_0
hom = expm(A*t) ;
invhom = inv(hom) ;
invhom_0 = subs(invhom,t,sym(t0)) ;
c_0 = invhom_0 * x_0 ;
hom_initialcond = hom * c_0 ;
should provide the correct solution for non-zero initial time.

How to solve equations with complex coefficients using ode45 in MATLAB?

I am trying to solve two equations with complex coefficients using ode45.
But iam getting an error message as "Inputs must be floats, namely single or
double."
X = sym(['[',sprintf('X(%d) ',1:2),']']);
Eqns=[-(X(1)*23788605396486326904946699391889*1i)/38685626227668133590597632 + (X(2)*23788605396486326904946699391889*1i)/38685626227668133590597632; (X(2)*23788605396486326904946699391889*1i)/38685626227668133590597632 + X(1)*(- 2500000 + (5223289665997855453060886952725538686654593059791*1i)/324518553658426726783156020576256)] ;
f=#(t,X)[Eqns];
[t,Xabc]=ode45(f,[0 300*10^-6],[0 1])
How can i fix this ? Can somebody can help me ?
Per the MathWorks Support Team, the "ODE solvers in MATLAB 5 (R12) and later releases properly handle complex valued systems." So the complex numbers are the not the issue.
The error "Inputs must be floats, namely single or double." stems from your definition of f using Symbolic Variables that are, unlike complex numbers, not floats. The easiest way to get around this is to not use the Symbolic Toolbox at all; just makes Eqns an anonymous function:
Eqns= #(t,X) [-(X(1)*23788605396486326904946699391889*1i)/38685626227668133590597632 + (X(2)*23788605396486326904946699391889*1i)/38685626227668133590597632; (X(2)*23788605396486326904946699391889*1i)/38685626227668133590597632 + X(1)*(- 2500000 + (5223289665997855453060886952725538686654593059791*1i)/324518553658426726783156020576256)] ;
[t,Xabc]=ode45(Eqns,[0 300*10^-6],[0 1]);
That being said, I'd like to point out that numerically time integrating this system over 300 microseconds (I assume without units given) will take a long time since your coefficient matrix has imaginary eigenvalues on the order of 10E+10. The extremely short wavelength of those oscillations will more than likely be resolved by Matlab's adaptive methods, and that will take a while to solve for a time span just a few orders greater than the wavelength.
I'd, therefore, suggest an analytical approach to this problem; unless it is a stepping stone another problem that is non-analytically solvable.
Systems of ordinary differential equations of the form
,
which is a linear, homogenous system with a constant coefficient matrix, has the general solution
,
where the m-subscripted exponential function is the matrix exponential.
Therefore, the analytical solution to the system can be calculated exactly assuming the matrix exponential can be calculated.
In Matlab, the matrix exponential is calculate via the expm function.
The following code computes the analytical solution and compares it to the numerical one for a short time span:
% Set-up
A = [-23788605396486326904946699391889i/38685626227668133590597632,23788605396486326904946699391889i/38685626227668133590597632;...
-2500000+5223289665997855453060886952725538686654593059791i/324518553658426726783156020576256,23788605396486326904946699391889i/38685626227668133590597632];
Eqns = #(t,X) A*X;
X0 = [0;1];
% Numerical
options = odeset('RelTol',1E-8,'AbsTol',1E-8);
[t,Xabc]=ode45(Eqns,[0 1E-9],X0,options);
% Analytical
Xana = cell2mat(arrayfun(#(tk) expm(A*tk)*X0,t,'UniformOutput',false)')';
k = 1;
% Plots
figure(1);
subplot(3,1,1)
plot(t,abs(Xana(:,k)),t,abs(Xabc(:,k)),'--');
title('Magnitude');
subplot(3,1,2)
plot(t,real(Xana(:,k)),t,real(Xabc(:,k)),'--');
title('Real');
ylabel('Values');
subplot(3,1,3)
plot(t,imag(Xana(:,k)),t,imag(Xabc(:,k)),'--');
title('Imaginary');
xlabel('Time');
The comparison plot is:
The output of ode45 matches the magnitude and real parts of the solution very well, but the imaginary portion is out-of-phase by exactly π.
However, since ode45's error estimator only looks at norms, the phase difference is not noticed which may lead to problems depending on the application.
It will be noted that while the matrix exponential solution is far more costly than ode45 for the same number of time vector elements, the analytical solution will produce the exact solution for any time vector of any density given to it. So for long time solutions, the matrix exponential can be viewed as an improvement in some sense.

matlab differential equation

I have the following differential equation which I'm not able to solve.
We know the following about the equation:
D(r) is a third grade polynom
D'(1)=D'(2)=0
D(2)=2D(1)
u(1)=450
u'(2)=-K * (u(2)-Te)
Where K and Te are constants.
I want to approximate the problem using a matrix and I managed to solve
the similiar equation: with the same limit conditions for u(1) and u'(2).
On this equation I approximated u' and u'' with central differences and used a finite difference method between r=1 to r=2. I then placed the results in a matrix A in matlab and the limit conditions in the vector Y in matlab and ran u=A\Y to get how the u value changes. Heres my matlab code for the equation I managed to solve:
clear
a=1;
b=2;
N=100;
h = (b-a)/N;
K=3.20;
Ti=450;
Te=20;
A = zeros(N+2);
A(1,1)=1;
A(end,end)=1/(2*h*K);
A(end,end-1)=1;
A(end,end-2)=-1/(2*h*K);
r=a+h:h:b;
%y(i)
for i=1:1:length(r)
yi(i)=-r(i)*(2/(h^2));
end
A(2:end-1,2:end-1)=A(2:end-1,2:end-1)+diag(yi);
%y(i-1)
for i=1:1:length(r)-1
ymin(i)=r(i+1)*(1/(h^2))-1/(2*h);
end
A(3:end-1,2:end-2) = A(3:end-1,2:end-2)+diag(ymin);
%y(i+1)
for i=1:1:length(r)
ymax(i)=r(i)*(1/(h^2))+1/(2*h);
end
A(2:end-1,3:end)=A(2:end-1,3:end)+diag(ymax);
Y=zeros(N+2,1);
Y(1) =Ti;
Y(2)=-(Ti*(r(1)/(h^2)-(1/(2*h))));
Y(end) = Te;
r=[1,r];
u=A\Y;
plot(r,u(1:end-1));
My question is, how do I solve the first differential equation?
As TroyHaskin pointed out in comments, one can determine D up to a constant factor, and that constant factor cancels out in D'/D anyway. Put another way: we can assume that D(1)=1 (a convenient number), since D can be multiplied by any constant. Now it's easy to find the coefficients (done with Wolfram Alpha), and the polynomial turns out to be
D(r) = -2r^3+9r^2-12r+6
with derivative D'(r) = -6r^2+18r-12. (There is also a smarter way to find the polynomial by starting with D', which is quadratic with known roots.)
I would probably use this information right away, computing the coefficient k of the first derivative:
r = a+h:h:b;
k = 1+r.*(-6*r.^2+18*r-12)./(-2*r.^3+9*r.^2-12*r+6);
It seems that k is always positive on the interval [1,2], so if you want to minimize the changes to existing code, just replace r(i) by r(i)/k(i) in it.
By the way, instead of loops like
for i=1:1:length(r)
yi(i)=-r(i)*(2/(h^2));
end
one usually does simply
yi=-r*(2/(h^2));
This vectorization makes the code more compact and can benefit the performance too (not so much in your example, where solving the linear system is the bottleneck). Another benefit is that yi is properly initialized, while with your loop construction, if yi happened to already exist and have length greater than length(r), the resulting array would have extraneous entries. (This is a potential source of hard-to-track bugs.)

Cryptic matlab error when computing eigs

I am trying to find the 2 eignevectors of the 2 smallest eigenvalues of a laplacian. I do this by
[v,c]=eigs(L,M,2,'SM');
Where L is the lapalcian and M is the mass matrix.
As a result I get the error
Error using eigs/checkInputs/LUfactorAminusSigmaB (line 1041)
The shifted operator is singular. The shift is an eigenvalue.
Try to use some other shift please.
Error in eigs/checkInputs (line 855)
[L,U,pp,qq,dgAsB] = LUfactorAminusSigmaB;
Error in eigs (line 94)
[A,Amatrix,isrealprob,issymA,n,B,classAB,k,eigs_sigma,whch, ...
Does this mean I am doing something wrong, or is this just matlab choosing a bad initial guess for its iteration process?
The matrices I am using should have a descent condition number...
I ran into the same problem while implementing normalized cuts segmentation. The condition number is actually infinite because the smallest eigenvalue is 0, and this is basically what MATLAB's error message is about. It's running LU decomposition first.
I just added a multiple of I, 10*eps*speye, to the normalized Laplacian to improve conditioning and that fixed it.
I had the same problem with the eigs function. So I went the long (and maybe stupid) way but it did the job for me as my problem is not that big: (I will try to keep your notation)
% Solve the eigenvalue problem using the full matrices
[v,c]=eig(full(L),full(M));
% Sort out the eigenvalues using the sort function (the "-" sign is because you want the smallest real eigenvalues in magnitude)
[E,P] = sort(real(c),'descend'); % Here I am assuming you know all the eigenvalues have` negative real parts
% Now P is a vector that contains (in order) the indices of the row permutation operated by the % function sort.
% In order to obtain the two eigenvectors corresponding to the 2 smallest eigenvalues:
for k = 1:2
index = P(k);
lambda(k) = c(index,index); % use this to check if c(index,index)=E(k,k)
eigvec(:,k) = v(:,index); % corresponding eigenvector
end
Hope this helps
G

Strange error when trying to compute cotangent

I'm new to MATLAB, and I'm trying to make sense of some scripts I have. In one, I have an expression for computing short-circuit impedance (within the context of other expressions):
Z=tan(2*p*f*d/vp)
That's fine and dandy, but when I want to change from tangent to the negative cotangent (for an open-circuit) like this:
Z=-1/tan(2*p*f*d/vp)
It gives me an error at that line as follows:
?? Error using ==> mldivide
Matrix dimensions must agree
Now, AFAIK none of the subexpressions in computing Z are matrices. What makes it more confusing is that if I change 1/tan with cot then it works (independently of whether I add a - sign in front of it or not):
Z=-cot(2*p*f*d/vp)
Any ideas? I've done my googling on the mldivide error, but I just don't see how that applies to computing the cotangent as literally the inverse of the tangent.
Am I missing a MATLAB peculiarity here? Thanks.
-- EDIT --
I think I should have included the entire source code (originally for calculating input impedance for a short-circuit line, and attempted a chance from tan to -cot for an open-circuit line)
close all; % close all opened graphs
figure; % open new graph
% define distributed line parameters
L=209.410e-9; % line inductance in H/m
C=119.510e-12; % line capacitance in F/m
vp=1/sqrt(L*C); % phase velocity
Z0=sqrt(L/C); % characteristic line impedance
d=0.1; % line length
N=5000; % number of sampling points
f=1e9+3e9*(0:N)/N; % set frequency range
%Z=tan(2*pi*f*d/vp); % short circuit impedance
Z= -1/tan(2*pi*f*d/vp); % open circuit impedance
plot(f/1e9,abs(Z0*Z));
title('Input impedance of a short-circuit transmission line');
xlabel('Frequency {\itf}, GHz');
ylabel('Input impedance |Z|, {\Omega}');
axis([1 4 0 500]);
% print -deps 'fig2_28.eps' % if uncommented -> saves a copy of plot in EPS format
I guess one of p, f, or d is a matrix, so tan(2*p*f*d/vp) will be a matrix as well. 1/matrix won't work because that is defined to be the inverse of a matrix multiplication, where you have restrictions to the dimensions of your matrices.
Try
Z=-1./tan(2*p*f*d/vp)
This is the element-wise division. (I assume that's what you want.)
That code works fine so long as p, f, d and vp are all scalar. Therefore, one of your inputs must be non-scalar.
The / sign is matrix division (i.e. multiplication by the inverse from the right), which needs same-sized arrays. Normally, all works well with scalars, but sometimes, the interpreter will cough so that you have to use ./, i.e. element-wise division, instead.
>> p = 0.1;
>> f = 0.2;
>> d = 0.01;
>> vp =0.2;
>> Z=-1/tan(2*p*f*d/vp)
Z =
-499.9993
It would seem that you are passing a matrix as Matlab tells you.