What is the difference between the two for loops? - arrays

I had a question which I hope someone is able to clarify for me. What is the difference between the following two for loops?
c = zeros(16,10);
for k = 1:10
c(1,k) = log(k+1) - log(k);
for n = 1:15
**c**(n+1,k) = 1./n - k*(c(n,k));
end
end
%%%%%
c = zeros(16,10);
for k = 1:10
c(1,k) = log(k+1) - log(k);
for n = 1:15
**A**(n+1,k) = 1./n - k*(c(n,k));
end
end
A lot of times I find myself trying different areas when its simply a result of a specification of matrix. In the 2nd code of the for loop, it does create a new matrix also but what are the difference in terms of the calculations ?
Thanks

Like noted, the capital C in the second program is very hard to notice. So I'm going to call it A.
After running the first program, say you have c1 matrix (c with all the calculations done).
The second program will produce 2 matrices A and c2. This c2 only has the first row of of the first c1, the rest of c2 is 0's. A will have the rest of c1, except for its first row, which is all 0's.
Hope this helps.

Related

Replace specific entries of a multidimensional arrays avoiding loops

I would like to replace the entry corresponding to the column number of an array that is part of a 3D matrix by zero. My matrix is of size IxJxJ. In each column j I can find a matrix of size IxJof which I would like to replace the jth column by zero.
You can find below an example of what I would like using a simple 3D matrix A. This example uses a loop, which is what I am trying to avoid.
A(:,:,1) = randi([1,2],5,3);
A(:,:,2) = randi([3,4],5,3);
A(:,:,3) = randi([5,6],5,3);
for i = 1:3
B = A(:,i,:);
B = squeeze(B);
B(:,i) = 0;
A(:,i,:) = B;
end
Firstly, you can replace the 4 lines of code in your for loop with just A(:,i,i) = 0;. I don't see any real need to avoid the for loop.
Using linear indexing, you can do
A((1:size(A,1)).'+size(A,1).*(size(A,2)+1).*(0:size(A,2)-1)) = 0
or for older version of Matlab without implicit expansion (pre-R2016b)
A(bsxfun(#plus,(1:size(A,1)).',size(A,1).*(size(A,2)+1).*(0:size(A,2)-1))) = 0
After some very quick testing, it actually looks like the bsxfun solution is fastest, but the differences aren't huge, your results may differ.
Use eye to create a logical mask and mutiply it by A.
A = A .* reshape(~eye(3), 1, 3, 3) ;

Output arrayfun into trid dimension of the matrix in MATLAB

Assume that I have a matrix A = rand(n,m). I want to compute matrix B with size n x n x m, where B(:,:,i) = A(:,i)*A(:,i)';
The code that can produce this is quite simple:
A = rand(n,m); B = zeros(n,n,m);
for i=1:m
B(:,:,i) = A(:,i)*A(:,i)'
end
However, I am concerned about speed and would like to ask you help to tell me how to implement it without using loops. Very likely that I need to use either bsxfun, arrayfun or rowfun, but I am not sure.
All answers are appreciated.
I don't have MATLAB at hand right now, but I think this code should produce the same result as your loop:
A1 = reshape(A,n,1,m);
A2 = reshape(A,1,n,m);
B = bsxfun(#times,A1,A2);
If you have a newer version of MATLAB, you don't need bsxfun any more, you can just write
B = A1 .* A2;
On older versions this last line will give an error message.
Whether any of this is faster than your loop depends also on the version of MATLAB. Newer MATLAB versions are not slow any more with loops. I think the loop is more readable, it's worth using more readable code, or at least keep the loop in a comment to clarify what the vectorized code does.
arrayfun and bsxfun does not speed up the calculations in my attempt as below:
clc;close all;
clear all;
m=300;n=400;
A = rand(n,m); B = zeros(n,n,m);
tic
for i=1:m
B(:,:,i) = A(:,i)*A(:,i)';
end
t1=toc
C = reshape(cell2mat(arrayfun(#(k) bsxfun(#times, A(:,k), A(:,k)'), ...
1:m, 'UniformOutput',false)),n,n,m);
%C=reshape(C,n,n,m);
t2=toc-t1
% t1 =0.3079
% t2 =0.5112

Using find for searching into the same array

I'm doing a project in MATLAB and I have a question about the find command.
I have an array (maxes) which contains data stored in two columns (time and frequency). Each row represent the frequency-time pair of a point.
I want to pair those values that meet certain conditions (that its frequency doesn't differ in more than 32 units and that its time doesn't differ in more than 64). I've thought of using the find command, but I don't know how to make it search for coincidences inside the same array. Is it possible? How can I do it?
In case I haven't explain my objective clearly (sorry if my English is bad, it's not my mother tongue), I leave here the code I've done for executing that part. It works perfectly, but it uses two for loops and I want to how it will work more efficiently using the find command.
for i = 1:length(maxes)-1
f1 = maxes(i,1);
t1 = maxes(i,2);
for j = i+1:length(maxes)
f2 = maxes(j,1);
t2 = maxes(j,2);
if((t2 - t1) < 64 && (t2 > t1))
if(abs(f2 - f1) < 32)
count = count+1;
Lrow = [t1, f1, f2 - f1, t2 - t1];
L(count,:) = Lrow;
end
else break;
end
end
end
Thank you so much in advance for your help
You can use meshgrid to efficiently solve this problem
[x1,x2]=meshgrid(maxes(:,1))
[y1,y2]=meshgrid(maxes(:,2))
xdiff=x1-x2
xind=find(xdiff<64)
xind=intersect(xind,find((x1-x2)>=0)
yind=find((y1-y2)<32)
ind=intersect(xind,yind)
Lrow=[x1(ind) y1(ind) x1-x2 y1-y2 ]
this should solve the problem.

How to change the values and do the functions Newton-Raphson

I need to iterate Newton-Raphson in MATLAB. It seems easy but I cannot figure out where I am wrong. The problem is:
For mmm=1:
1) If m=1 take c1=c1b and c2=1-c1 and do the loop for u1,2(i) and p1,2(i)
2)If m=2 take c1=c1+dc and c2=1-c1, and this time do the loop with new c1 and c2 for u1,2(i) and p1,2(i)
3) If m=3 take c1=(c1*st(1)-(c1-dc)*st(2))/(st(1)-st(2)) and do the loop for new c1 and c2.
Then increase the iteration number: mmm=2 ;
mmm keeps count of the number of N-R iterations. The first iteration has mmm=1, the second mmm=2, etc. (This particular run only do 2 iterations).
sumint are inside of the integrals.
I need to plot these figures in the code but MATLAB gives errors below. Please help me.
Relevant part of the code:
ii=101;
u = cell(2, 1);
ini_cond = [0,0];
for i = 1:2;
u{i} = zeros(1,ii);
u{i}(:, ii) = ini_cond(i) * rand(1, 1);
end
for i=1:ii;
fikness=fik*sin(pi.*x);
u{1}(i)=(c1-H1D*(x-0.5)+AD/2.*(x-0.5).^2)./(H1-0.5*fikness-A*(x-0.5));
u{2}(i)=(c2+H1D*(x-0.5)-AD/2.*(x-0.5).^2)./(1.-H1+0.5*fikness+A*(x-0.5));
end
p = cell(2, 1);
q = cell(2, 1);
for i = 1:2;
p{i} = zeros(1,ii);
q{i} = zeros(1,ii);
end
p{1}(1)=0.5*(1.-u{1}(1).^2);
q{1}(1)=0;
p{2}(1)=0.5*(1.-u{2}(1).^2);
q{2}(1)=0;
for i=2:101
q{1}(i)=q{1}(i-1)-dx*(u{1}(i-1)-ub{1}(i-1))./dt;
p{1}(i)=0.5*(1.-u{1}(i).^2)+q{1}(i);
q{2}(i)=q{2}(i-1)-dx*(u{2}(i-1)-ub{2}(i-1))./dt;
p{2}(i)=0.5*(1.-u{2}(i).^2)+q{2}(i);
end
st = zeros(2, length(t));
st(1,:)=p{1}(100)-p{2}(100);
m=m+1;
if m==3;
c1=(c1*st(1)-(c1-dc)*st(2))/(st(1)-st(2));
c2=1-c1;
end
for i = 1:2;
sumint{i} = zeros(1,length(t));
end
sumint = cell(2, 1);
sumint{1}(1)=0.5*(p{2}(1)-p{1}(1));
sumint{2}(1)=0.5*(p{2}(1)-p{1}(1)).*(-1/2);
for i=2:ii-1;
x=(i-1)*dx;
sumint{1}(i)=sumint{1}(i-1)+(p{2}(i)-p{1}(i));
sumint{2}(i)=sumint{2}(i-1)+(p{2}(i)-p{1}(i))*(x-1/2);
end
H1DDOT=-sumint{1}.*dx./rmass;
H1D=H1D+dt*H1DDOT;
H1=H1+dt*H1D;
ADDOT=sumint{2}*dx./rmomi;
AD=AD+dt*ADDOT;
A=A+dt*AD;
H1L=H1+A.*0.5;
H1R=H1-A.*0.5;
H2=1.-H1;
rat1=AD./ADinit;
rat2=ADDOT./AD;
u are the velocities p are the pressures c1,c2 are the camber effects H1DDOT and ADDOT are the second derivation of H1 and A. sum1 and sum2 are the inside of the integrals to define the values of H1DDOT and ADDOT. H1DDOT and ADDOT are functions of time.
As you can see from the message, the error is with this line:
sumint{2}(i)=sumint{2}(i-1)+(p{2}(i)-p{1}(i)).*(x-1/2);
Now, let's find out why:
sumint{2}(i) = ...
This part means you want to insert whatever is on the right side to the ith position of the array in cell sumint{2}. That means, the right side must be a scalar.
Is it?
Well, sumint{2}(i-1)+(p{2}(i)-p{1}(i)) is certainly a scalar, since you use a single value as index to all the vectors/arrays. The problem is the multiplication .*(x-1/2);.
From the code above, it is clear that x is a vector / array, (since you use length(x) etc). Multiplying the scalar sumint{2}(i-1)+(p{2}(i)-p{1}(i)), by the vector x, will give you back a vector, which as mentioned, will not work.
Maybe you want the ith value of x?
There are several other strange things going on in your code, for instance:
for i=1:101;
fikness=fik*sin(pi.*x);
u{1}=(c1-H1D*(x-0.5)+AD/2.*(x-0.5).^2)./(H1-0.5*fikness-A*(x-0.5));
u{2}=(c2+H1D*(x-0.5)-AD/2.*(x-0.5).^2)./(1.-H1+0.5*fikness+A*(x-0.5));
end
Why do you have a loop here? You are not looping anything, you are doing the same calculations 100 times. Again, I guess it should be x(i).
Update:
Your new error is introduced because you changed x into a scalar. Then u = zeros(1,length(x)) will only be a scalar, meaning u{1}(i) will fail for i ~= 1.

Matlab: Summation over Array Dimensions

I've done quite a bit of searching and haven't been able to find a satisfactory answer so far, so I'm sorry if this question has already been raised.
I'm stuck on how to sum over the dimensions of an array. I have array A(w0,lambda,2048,2048), and I would like to be able to define a second array U(w0, 2048, 2048) which is composed of the sum of A over dimension lambda.
So far I have been defining both A and U as follows:
A = zeros(length(w0),length(lambda),2048,2048);
U = zeros(length(w0),2048,2048);
for ii = 1:length(w0) % Scan through spot sizes
for aa = 1:length(lambda) % Scan through wavelengths
A(ii,aa,:,:) = ASM(w0(ii),lambda(aa),z1,z2);
end
U(ii,:,:) = sum(A,2);
end
Where ASM is just a function. z1 and z2 are defined earlier, and not relevant here.
I have been trying to come up with other possible ways of finding U(w0,2048,2048) as the sum over the second dimension of A (lambda), but haven't been successful...
Thanks for any pointers, and sorry again if this has already been resolved!
James.
From the sounds of it, you just want:
U = squeeze(sum(A, 2));
squeeze() eliminates singleton dimensions.
Here are two alternative solutions:
U = reshape(sum(A, 2), [length(w0) 2048 2048]);
or:
U = sum(A, 2);
U = U(:, 1, :, :);
Try using 'sum' function with a dimension argument, and collapse result on the desired dimensions.
z = rand(2,3,2,2);
q = sum(z,2); %sum all 3 matrices of size 2x2x2 to get 2x1x2x2 result
zz = q(:,1,:,:); %zz is now 2x2x2, by collapsing the dimension 2.

Resources