Cubic Spline MATLAB wrong result - matlab

I made Clamped Cubic Spline code.
But when I put
f_ = CubicSpline([0,1,2,3],[exp(0),exp(1),exp(2),exp(3)],exp(0),exp(3));
and get answer by sym2poly(f_(1))
result is quite different from my lecture note. And actually, my Cubic Spline result even doesn't match to the prime of bound...
Please I can't understand what is the problem in my code.
This is what I used for my algorithm.
function [f_] = CubicSpline(x0,f0,FPO,FPN)
syms x;
n = length(x0);
h = zeros(n,1);
alpha = zeros(n,1);
l = zeros(n,1);
u = zeros(n,1);
z = zeros(n,1);
a = zeros(n,1);
b = zeros(n,1);
c = zeros(n,1);
d = zeros(n,1);
for iter = 1:n-1
h(iter) = x0(iter+1)-x0(iter);
end
alpha(1) = 3*(f0(2)-f0(1))/h(1)-3*FPO;
alpha(n) = 3*FPN-3*(f0(n)-f0(n-1))/h(n-1);
for iter = 1:n
a(iter) = f0(iter);
end
for iter = 2:n-1
alpha(iter) = 3/h(iter)*(f0(iter+1)-f0(iter))-3/h(iter-1)*(f0(iter)-f0(iter-1));
end
l(1) = 2*h(1);
u(1) = 0.5;
z(1) = f0(1)/l(1);
for iter = 2:n-1
l(iter) = 2*(x0(iter+1)-x0(iter-1)) - h(iter-1)*u(iter-1);
u(iter) = h(iter)/l(iter);
z(iter) = (alpha(iter)-h(iter-1)*z(iter-1))/l(iter);
end
l(n) = h(n-1)*(2-u(n-1));
z(n) = (alpha(n)-h(n-1)*z(n-1))/l(n);
c(n) = z(n);
for iter = (n-1):-1:1
c(iter) = z(iter)-u(iter)*c(iter+1);
b(iter) = (f0(iter+1)-f0(iter))/h(iter)-h(iter)*(c(iter+1)+2*c(iter))/3;
d(iter) = (c(iter+1)-c(iter))/(3*h(iter));
end
for iter = 1:n-1
f_(iter) = a(iter) + b(iter)*(x-x0(iter)) + c(iter)*(x-x0(iter))^2 + d(iter)*(x-x0(iter))^3;
end
end

There is a typo in your code for step 4
z(1) = f0(1)/l(1);
should be
z(1) = alpha(1)/l(1);

Related

QR factorization,matlab

%% Gram—Schmidt as Triangular Orthogonalization
clear
M = [1,1,1; 1,1,0; 1,1,9]
[m,n] = size(M);
Q = M;
Rinv = eye(n);
for i = 1:n
Ri = eye(n);
Ri(i,i) = 1 / norm(Q(:,i));
for j = i+1:n
Ri(i,j) = -Q(:,i)'*Q(:,j) / norm(Q(:,i));
end
Q = Q*Ri;
Rinv = Rinv*Ri;
end
Q
R = inv(Rinv)
The question: Q*R gives M butQ is not orthagonal.
This should return the correct result:
clear();
M = [1,1,1; 1,1,0; 1,1,9];
[m,n] = size(M);
Q = zeros(m,n);
R = zeros(n,n);
for j = 1:n
v = M(:,j);
for i = 1:j-1
R(i,j) = Q(:,i).' * M(:,j);
v = v - (R(i,j) * Q(:,i));
end
R(j,j) = norm(v);
Q(:,j) = v / R(j,j);
end
Alternatively, you could give a try to the following implementation I found on Matlab File Exchange (it contains many know variants of the algorithm): https://it.mathworks.com/matlabcentral/fileexchange/55881-gram-schmidt-orthogonalization

Finding the distribution of '1' in rows/columns from a parity-check matrix

My question this time concerns the obtention of the degree distribution of a LDPC matrix through linear programming, under the following statement:
My code is the following:
function [v] = LP_Irr_LDPC(k,Ebn0)
options = optimoptions('fmincon','Display','iter','Algorithm','interior-point','MaxIter', 4000, 'MaxFunEvals', 70000);
fun = #(v) -sum(v(1:k)./(1:k));
A = [];
b = [];
Aeq = [0, ones(1,k-1)];
beq = 1;
lb = zeros(1,k);
ub = [0, ones(1,k-1)];
nonlcon = #(v)DensEv_SP(v,Ebn0);
l0 = [0 rand(1,k-1)];
l0 = l0./sum(l0);
v = fmincon(fun,l0,A,b,Aeq,beq,lb,ub,nonlcon,options)
end
Definition of nonlinear constraints:
function [c, ceq] = DensEv_SP(v,Ebn0)
% It is also needed to modify this function, as you cannot pass parameters from others to it.
h = [0 rand(1,19)];
h = h./sum(h); % This is where h comes from
syms x;
X = x.^(0:(length(h)-1));
R = h*transpose(X);
ebn0 = 10^(Ebn0/10);
Rm = 1;
LLR = (-50:50);
p03 = 0.3;
LLR03 = log((1-p03)/p03);
r03 = 1 - p03;
noise03 = (2*r03*Rm*ebn0)^-1;
pf03 = normpdf(LLR, LLR03, noise03);
sumpf03 = sum(pf03(1:length(pf03)/2));
divisions = 100;
Aj = zeros(1, divisions);
rho = zeros(1, divisions);
xj = zeros(1, divisions);
k = 10; % Length(v) -> Same value as in 'Complete.m'
for j=1:1:divisions
xj(j) = sumpf03*j/divisions;
rho(j) = subs(R,x,1-xj(j));
Aj(j) = 1 - rho(j);
end
c = zeros(1, length(xj));
lambda = zeros(1, length(Aj));
for j = 1:1:length(xj)
lambda(j) = sum(v(2:k).*(Aj(j).^(1:(k-1))));
c(j) = sumpf03*lambda(j) - xj(j);
end
save Almacen
ceq = [];
%ceq = sum(v)-1;
end
This question is linked to the one posted here. My problem is that I need that each element from vectors v and h resulting from this optimization problem is a fraction of x/N and x/(N(1-r) respectively.
How could I ensure that condition without losing convergence capability?
I came up with one possible solution, at least for vector h, within the function DensEv_SP:
function [c, ceq] = DensEv_SP(v,Ebn0)
% It is also needed to modify this function, as you cannot pass parameters from others to it.
k = 10; % Same as in Complete.m, desired sum of h
M = 19; % Number of integers
h = [0 diff([0,sort(randperm(k+M-1,M-1)),k+M])-ones(1,M)];
h = h./sum(h);
syms x;
X = x.^(0:(length(h)-1));
R = h*transpose(X);
ebn0 = 10^(Ebn0/10);
Rm = 1;
LLR = (-50:50);
p03 = 0.3;
LLR03 = log((1-p03)/p03);
r03 = 1 - p03;
noise03 = (2*r03*Rm*ebn0)^-1;
pf03 = normpdf(LLR, LLR03, noise03);
sumpf03 = sum(pf03(1:length(pf03)/2));
divisions = 100;
Aj = zeros(1, divisions);
rho = zeros(1, divisions);
xj = zeros(1, divisions);
N = 20; % Length(v) -> Same value as in 'Complete.m'
for j=1:1:divisions
xj(j) = sumpf03*j/divisions;
rho(j) = subs(R,x,1-xj(j));
Aj(j) = 1 - rho(j);
end
c = zeros(1, length(xj));
lambda = zeros(1, length(Aj));
for j = 1:1:length(xj)
lambda(j) = sum(v(2:k).*(Aj(j).^(1:(k-1))));
c(j) = sumpf03*lambda(j) - xj(j);
end
save Almacen
ceq = (N*v)-floor(N*v);
%ceq = sum(v)-1;
end
As above stated, there is no longer any problem with vector h; nevertheless the way I defined ceq value seemed to be insufficient to make the optimization work out (the problems with v have not diminished at all). Does anybody know how to find the solution?

Matlab Code for Linear System by Central Difference Method

I have a linear system Ay = b, which is created by matrix looks like this:
Here attempt to find the curves based on the matrix in the image description:
n = 10;
x0 = 0;
xn = 1;
h = 1/n;
y0 = 0;
y1 = 0;
x = zeros(1:n-1);
for i = 1:n-1;
x(i) = i*h
end
A =zeros(n-1);
for j = 1:n-2;
A(j,j+1) = (1+h/2);
A(j,j) = (h*exp(x(j))-2);
A(j+1,j) = (1-h/2);
end
A(n-1,n-1) = (h*exp(x(n-1))-2);
b = zeros(1,n-1); %Right-hand side vector
for i = 1:n-1
b(i)=h^2*((exp(x(i))-pi^2)*sin(pi*x(i))+pi*cos(pi*x(i)));
end
b=b';
y = zeros(1,n-1);
y = inv(A)*b % Solving for y
figure
plot(x,y,x,sin(x))
This is code that I create but the curves disappear, anyone can help me to check my code?

Vectorizing 4 nested for loops

I'm trying to vectorize the 2 inner nested for loops, but I can't come up with a way to do this. The FS1 and FS2 functions have been written to accept argument for N_theta and N_e, which is what the loops are iterating over
%% generate regions
for raw_r=1:visual_field_width
for raw_c=1:visual_field_width
r = raw_r - center_r;
c = raw_c - center_c;
% convert (r,c) to polar: (eccentricity, angle)
e = sqrt(r^2+c^2)*deg_per_pixel;
a = mod(atan2(r,c),2*pi);
for nt=1:N_theta
for ne=1:N_e
regions(raw_r, raw_c, nt, ne) = ...
FS_1(nt-1,a,N_theta) * ...
FS_2(ne-1,e,N_e,e0_in_deg, e_max);
end
end
end
end
Ideally, I could replace the two inner nested for loops by:
regions(raw_r,raw_c,:,:) = FS_1(:,a,N_theta) * FS_2(:,N_e,e0_in_deg,e_max);
But this isn't possible. Maybe I'm missing an easy fix or vectorization technique? e0_in_deg and e_max are parameters.
The FS_1 function is
function h = FS_1(n,theta,N,t)
if nargin==2
N = 9;
t=1/2;
elseif nargin==3
t=1/2;
end
w = (2*pi)/N;
theta = theta + w/4;
if n==0 && theta>(3/2)*pi
theta = theta - 2*pi;
end
h = FS_f((theta - (w*n + 0.5*w*(1-t)))/w);
the FS_2 function is
function g = FS_gne(n,e,N,e0, e_max)
if nargin==2
N = 10;
e0 = .5;
elseif nargin==3
e0 = .5;
end
w = (log(e_max) - log(e0))/N;
g = FS_f((log(e)-log(e0)-w*(n+1))/w);
and the FS_f function is
function f = FS_f(x, t)
if nargin<2
t = 0.5;
end
f = zeros(size(x));
% case 1
idx = x>-(1+t)/2 & x<=(t-1)/2;
f(idx) = (cos(0.5*pi*((x(idx)-(t-1)/2)/t))).^2;
% case 2
idx = x>(t-1)/2 & x<=(1-t)/2;
f(idx) = 1;
% case 3
idx = x>(1-t)/2 & x<=(1+t)/2;
f(idx) = -(cos(0.5*pi*((x(idx)-(1+t)/2)/t))).^2+1;
I had to assume values for the constants, and then used ndgrid to find the possible configurations and sub2ind to get the indices. Doing this I removed all loops. Let me know if this produced the correct values.
function RunningFunction
%% generate regions
visual_field_width = 10;
center_r = 2;
center_c = 3;
deg_per_pixel = 17;
N_theta = 2;
N_e = 5;
e0_in_deg = 35;
e_max = 17;
[raw_r, raw_c, nt, ne] = ndgrid(1:visual_field_width, 1:visual_field_width, 1:N_theta, 1:N_e);
ind = sub2ind(size(raw_r), raw_r, raw_c, nt, ne);
r = raw_r - center_r;
c = raw_c - center_c;
% convert (r,c) to polar: (eccentricity, angle)
e = sqrt(r.^2+c.^2)*deg_per_pixel;
a = mod(atan2(r,c),2*pi);
regions(ind) = ...
FS_1(nt-1,a,N_theta) .* ...
FS_2(ne-1,e,N_e,e0_in_deg, e_max);
regions = reshape(regions, size(raw_r));
end
function h = FS_1(n,theta,N,t)
if nargin==2
N = 9;
t=1/2;
elseif nargin==3
t=1/2;
end
w = (2*pi)./N;
theta = theta + w/4;
theta(n==0 & theta>(3/2)*pi) = theta(n==0 & theta>(3/2)*pi) - 2*pi;
h = FS_f((theta - (w*n + 0.5*w*(1-t)))/w);
end
function g = FS_2(n,e,N,e0, e_max)
if nargin==2
N = 10;
e0 = .5;
elseif nargin==3
e0 = .5;
end
w = (log(e_max) - log(e0))/N;
g = FS_f((log(e)-log(e0)-w*(n+1))/w);
end
function f = FS_f(x, t)
if nargin<2
t = 0.5;
end
f = zeros(size(x));
% case 1
idx = x>-(1+t)/2 & x<=(t-1)/2;
f(idx) = (cos(0.5*pi*((x(idx)-(t-1)/2)/t))).^2;
% case 2
idx = x>(t-1)/2 & x<=(1-t)/2;
f(idx) = 1;
% case 3
idx = x>(1-t)/2 & x<=(1+t)/2;
f(idx) = -(cos(0.5*pi*((x(idx)-(1+t)/2)/t))).^2+1;
end

Using Fast Fourier Transform on matlab?

I am having some difficulty in solving a simple 2D Poisson equation in Matlab using spectral methods in one direction on finite difference in the other.
I am obtaining a scaled version of the correct answer but can't work out why although I think it has something to do with the wavenumber.
Any help would be greatly appreciated, the code can be seen below.
N = 32;
x = ((0:N-1)/N)*2*pi;
y = ((0:N-1)/N)*2*pi;
dx = 2*pi/N;
k = fftshift(-N/2:N/2-1);
[X,Y] = meshgrid(x,y);
f = (-2)*cos(X).*sin(Y);
f_comparison = cos(X).*sin(Y);
checker = 10;
u = zeros(N,N);
u_new = zeros(N,N);
f_hat = fftn(f);
while checker > 1*10^(-7);
u_new_hat = fftn(u_new);
for aa = 1:N
for a = 1:N
q1 = a+1;
q2 = a-1;
if q2 == 0
q2 = N;
end
if q1 == N+1
q1 = 1;
end
denom = ((dx^2)*((k(aa))^2))+2;
u_new_hat(a,aa) = (1/denom)*((u_new_hat(q1,aa))+(u_new_hat(q2,aa))-((f_hat(a,aa))*(dx^2)));
end
end
u_new = real(ifftn(u_new_hat));
for aa = 1:N
for a = 1:N
u_checker(a,aa) = abs(u_new(a,aa)-u(a,aa));
end
end
compare = max(u_checker);
checker = max(compare);
for aa = 1:N
for a = 1:N
u(a,aa) = u_new(a,aa);
end
end
end
%calculate scaling discrepency
ddd = f_comparison./u;