Matrix indexing error in MATLAB - matlab

I keep getting this error in Matlab:
Attempted to access r(0,0); index must be a positive integer or
logical.
Error in ==> Romberg at 15
I ran it with Romberg(1.3, 2.19,8)
I think the problem is the statement is not logical because I made it positive and still got the same error. Anyone got some ideas of what i could do?
function Romberg(a, b, n)
h = b - a;
r = zeros(n,n);
for i = 1:n
h = h/2;
sum1 = 0;
for k = 1:2:2^(i)
sum1 = sum1 + f(a + k*h);
end
r(i,0) = (1/2)*r(i-1,0) + (sum1)*h;
for j = 1:i
r(i,j) = r(i,j-1) + (r(i,j-1) - r(i-1,j-1))/((4^j) - 1);
end
end
disp(r);
end
function f_of_x = f(x)
f_of_x = sin(x)/x;
end

There are two lines where you're using 0 to index, which you can't in Matlab:
r(i,0) = (1/2)*r(i-1,0) + (sum1)*h;
and
r(i,j) = r(i,j-1) + (r(i,j-1) - r(i-1,j-1))/((4^j) - 1);
when j==1 or i==1.
I suggest that you run your loops starting from 2, and replace the exponents i and j with (i-1) and (j-1), respectively.
As an aside: You could write the loop
for k = 1:2:2^(i)
sum1 = sum1 + f(a + k*h);
end
as
k = 1:2:2^i;
tmp = f(a + k*h);
sum1 = sum(tmp);
if you write f_of_x as
sin(x)./x

In MATLAB, vectors and matrices are indexed starting from 1. Therefore, the very first line of your code is invalid because the index on r is 0.

You have zero subscripts in
r(i,0) = (1/2)*r(i-1,0) + (sum1)*h;
This is impossible in MATLAB -- all indices start form 1.

Related

Filling MATLAB array using formula and arrays of values

I want to fill a 10x15 matrix in MATLAB using the formula z(i, j) = 2 * x(i) + 3 * y(j)^2, so that each entry at (i, j) = z(i, j). I have arrays for x and y, which are of size 10 and 15, respectively.
I've accomplished the task using the code below, but I want to do it in one line, since I'm told it's possible. Any thoughts?
x = linspace(0,1,10);
y = linspace(-0.5,0.5,15);
z = zeros(10,15);
m_1 = 2;
m_2 = 3;
for i = 1:length(x)
for j = 1:length(y)
z(i, j) = m_1*x(i) + m_2*y(i)^2;
end
end
It looks like you have a bug in your original loop:
You are using i index twice: m_1*x(i) + m_2*y(i)^2.
The result is that all the columns of z matrix are the same.
For applying the formula z(i, j) = 2*x(i) + 3*y(j)^2 use the following loop:
x = linspace(0,1,10);
y = linspace(-0.5,0.5,15);
z = zeros(10,15);
m_1 = 2;
m_2 = 3;
for i = 1:length(x)
for j = 1:length(y)
z(i, j) = m_1*x(i) + m_2*y(j)^2;
end
end
For implementing the above loop using one line, we may use meshgrid first.
Replace the loop with:
[Y, X] = meshgrid(y, x);
Z = m_1*X + m_2*Y.^2;
For expansions, read the documentation of meshgrid, it is much better than any of the expansions I can write...
The following command gives the same output as your original loop (but it's probably irrelevant):
Z = repmat((m_1*x + m_2*y(1:length(x)).^2)', [1, length(y)]);
Testing:
max(max(abs(Z - z)))
ans =
0

Populating matrix with for loop depending if index is even or odd

This is a part of a PDE problem that I'm trying to solve numerically. I know that my calculations for the entries are correct, however I'm struggling to assemble the matrix properly in Matlab. The first rows are correct, however the two last rows are not correct since I'm missing the elements a_{11,10}, a_{10,10} and a_{10,11}. I'm missing these because my loop never accesses them. For for example a_{10,10} requires i = 10, which is an even number, however my M = 11 in this case and i only goes from 1 to 9. If I make my for loop go from 1:11, I get out of bounds error since I'm using indecies i+1 and i+2.
The same goes for the vector b. How do I fill in all my b_i's if i only goes to 9 but the vector is 11 elements long?
Any suggestion on how to fix this? I've tried making separate for loops for the odd and even case but I'm still having the same problem of entries missing due to using indecies i+1 and i+2. Or do I manually have to enter (hardcode) these indecies outside of the foor loop?
Here is my loop:
h = 1/10;
x = 0:h:1;
M = length(x);
% Assemble stiffness matrix A and load vector b.
A = zeros(M,M);
b = zeros(M,1);
for i = 1:M-2
if rem(i,2) ~= 0 % if i is odd
A(i,i) = A(i,i) + 1/(3*h);
b(i) = b(i) + f(x(i)) * (-2)*h/3;
elseif rem(i,2) == 0 % if i is even
A(i,i) = A(i,i) + 3/(3*h);
A(i+2,i) = A(i+2,i) - 8/(3*h);
A(i,i+2) = A(i,i+2) - 8/(3*h);
b(i) = b(i) + f(x(i)) * 8*h/3;
end
A(i+1,i) = A(i+1,i) + 2/(3*h);
A(i,i+1) = A(i,i+1) - 3/(3*h);
end
% Enforce the boundary conditions
A(1,1) = 1.e4;
A(end,end) = 1.e4;
I think you can simply pad matrix A with two extra rows and columns, and remove them later:
Look at the following modified version of your code:
h = 1/10;
x = 0:h:1;
M = length(x);
% Assemble stiffness matrix A and load vector b.
%Initialize A to have two more rows and columns.
A = zeros(M+2);
b = zeros(M,1);
for i = 1:M
if rem(i,2) ~= 0 % if i is odd
A(i,i) = A(i,i) + 1/(3*h);
b(i) = b(i) + f(x(i)) * (-2)*h/3;
elseif rem(i,2) == 0 % if i is even
A(i,i) = A(i,i) + 3/(3*h);
A(i+2,i) = A(i+2,i) - 8/(3*h);
A(i,i+2) = A(i,i+2) - 8/(3*h);
b(i) = b(i) + f(x(i)) * 8*h/3;
end
A(i+1,i) = A(i+1,i) + 2/(3*h);
A(i,i+1) = A(i,i+1) - 3/(3*h);
end
%Remove two rows and columns form matrix A.
A = A(1:end-2, 1:end-2);
% Enforce the boundary conditions
A(1,1) = 1.e4;
A(end,end) = 1.e4;
function z = f(t)
% Stab f functionn - f(x) return x
z = t;
end
I hope the code behaves as you expected (it's not so clear what value you are expecting to read outside the bounds of A)...

How can I vectorize slow code in MATLAB to increase peformance?

How can I vectorize this code? At the moment it runs so slow. I'm really stuck and I've spent the last couple of hours trying to vectorize it, however I can't seem to get it to work correctly.
My naive program below works incredibly slowly. N should really be 10,000 but the program is struggling with N = 100. Any advice would be appreciated.
The code wants to iterate through the functions given N times for each value w21. It then plots the last 200 values for each value of w21. The code below does work as expected in terms of the plot but as mentioned is far to slow since for a good plot the values need to be in the thousands.
hold on
% Number of iterations
N = 100;
x = 1;
y = 1;
z = 1;
for w21 = linspace(-12,-3,N)
for i = 1:N-1
y = y_iterate(x,z,w21);
z = z_iterate(y);
x = x_iterate(y);
if i >= (N - 200)
p = plot(w21,x,'.k','MarkerSize',3);
end
end
end
Required functions:
function val = x_iterate(y)
val = -3 + 8.*(1 ./ (1 + exp(-y)));
end
function val = z_iterate(y)
val = -7 + 8.*(1 ./ (1 + exp(-y)));
end
function val = y_iterate(x,z,w21)
val = 4 + w21.*(1 ./ (1 + exp(-x))) + 6.*(1 ./ (1 + exp(-z)));
end
I believe it's because of plot. Try:
[X,Y,Z] = deal( zeros(N,N-1) );
w21 = linspace(-12,-3,N);
for i = 1:N
for j = 1:N-1
y = y_iterate(x,z,w21(i));
z = z_iterate(y);
x = x_iterate(y);
X(i,j) = x;
Y(i,j) = y;
Z(i,j) = z;
end
end
nn = max(1,N-200);
plot(w21,X(nn:end,:),'.k')

MATLAB sparse matrices: Gauss Seidel and power method using a sparse matrix with CSR (Compressed Sparse Row)

this is my first time here so I hope that someone can help me.
I'm trying to implementing the Gauss-Seidel method and the power method using a matrix with the storage CSR or called Morse storage. Unfortunately I can't manage to do better then the following codes:
GS-MORSE:
function [y] = gs_morse(aa, diag, col, row, nmax, tol)
[n, n] = size(A);
y = [1, 1, 1, 1];
m = 1;
while m < nmax,
for i = 1: n,
k1 = row(i);
k2 = row(i + 1) - 1;
for k = k1: k2,
y(i) = y(i) + aa(k) * x(col(k));
y(col(k)) = y(col(k)) + aa(k) * diag(i);
end
k2 = k2 + 1;
y(i) = y(i) + aa(k) * diag(i);
end
if (norm(y - x)) < tol
disp(y);
end
m = m + 1;
for i = 1: n,
x(i) = y(i);
end
end
POWER-MORSE:
I was able only to implement the power method but I don't understand how to use the former matrix... so my code for power method is:
function [y, l] = potencia_iterada(A, v)
numiter=100;
eps=1e-10;
x = v(:);
y = x/norm(x);
l = 0;
for k = 1: numiter,
x = A * y;
y = x / norm(x);
l0 = x.' * y;
if abs(l0) < eps
return
end
l = l0;
end
Please anyone can help me for completing these codes or can explain me how can I do that? I really don't understand how to do. Thank you very much

how to remove array index out of bound error in matlab

here is my code where i have one error regarding array index out out of bound. plzz help me to rectify it
I = imread('E:\degraded images\village.jpg');
imshow(I)
I = im2double(I);
I = log(1 + I);
M = 2*size(I,1) + 1;
N = 2*size(I,2) + 1;
sigma = 10;
[X, Y] = meshgrid(1:N,1:M);
centerX = ceil(N/2);
centerY = ceil(M/2);
gaussianNumerator = (X - centerX).^2 + (Y - centerY).^2;
H = exp(-gaussianNumerator./(2*sigma.^2));
H = 1 - H;
imshow(H,'InitialMagnification',25)
H = fftshift(H);
If = fft2(I, M, N);
Iout = real(ifft2(H.*If)); ** here the code has error . ??? Error using ==> times Number of array dimensions must match for binary array op.**
H is 2-D while If is 3-D. You can use repmat with H or subset If. I don't know which one is correct for your situation. For instance,
rempat( H, [1, 1, 3 ] ) .* If;
or
H .* If(:,:,ind); % ind is the index of the 2-D array you want to subset