Increment a for loop by 3 then by 1 using matlab - arrays

I am working on MATLAB code right now, and I want to increament y by 3 then by 1 and so on.
Here is the code if anyone could help, it would be appreciated.
for y=1:2:9
for x=9:-1:1
A(x,y)=1
if x==1 && y~=9
%y=y+1
for x= 1:9
A(x,y)=1
end
end
end
end

You first make a vector of the indexes you want to visit and then loop over the vector.
idx = [1,2,5]; %and so on
for ct = 1:length(idx)
A(x,y(idx(ct)))=1
end

You can specify a predefined vector or even matrix to be used in for loop; not necessary to use range index.

I am not completely certain how your question is reflected in your code. However, if you want to alternately increment y with 1 and 3, I would make a standard for-loop and then update y inside. Something like:
n = 100;
for i = 1:n
y = y + 2*mod(i,2)+1;
display(y) %Do things
end

Related

VBA for loop with negative step, k, calling array(k+1). What will it do?

For k = kT To 0 Step -1
ThKC(k + 1) = ThKCl
.
.
.
next k
Suppose I have kT as 5000. ThkCl is a constant value. During the first iteration when I say (k+1), what will be the index of ThKC array?
I have no idea about VBA and need a script changed to python. So I'm just looking for the logic in the script. I also have the same script in Fortran90 too, but VBA seemed easier to understand. Any tips on the migration are also welcome.
Just guessing, that what you have in mind could be:
kT = 5000
For k = kT To 0 Step -1
ThKC(k) = ThKCl
' Do other tasks.
Next
That would loop from 5000 to 0.

A matrix and a column vector containing indices, how to iterate with no loop?

I have a big matrix (500212x7) and a column vector like below
matrix F vector P
0001011 4
0001101 3
1101100 6
0000110 1
1110000 7
The vector contains indices considered within the matrix rows. P(1) is meant to point at F(1,4), P(2) at F(2,3) and so on.
I want to negate a bit in each row in F in a column pointed by P element (in the same row).
I thought of things like
F(:,P(1)) = ~F(:,P(1));
F(:,P(:)) = ~F(:,P(:));
but of course these scenarios won't produce the result I expect as the first line won't make P element change and the second one won't even let me start the program because a full vector cannot make an index.
The idea is I need to do this for all F and P rows (changing/incrementing "simultaneously") but take the value of P element.
I know this is easily achieved with for loop but due to large dimensions of the F array such a way to solve the problem is completely unacceptable.
Is there any kind of Matlab wizardry that lets solving such a task with the use of matrix operations?
I know this is easily achieved with for loop but due to large dimensions of the F array such a way to solve the problem is completely unacceptable.
You should never make such an assumption. First implement the loop, then check to see if it really is too slow for you or not, then worry about optimizing.
Here I'm comparing Luis' answer and the trival loop:
N = 500212;
F = rand(N,7) > 0.6;
P = randi(7,N,1);
timeit(#()method1(F,P))
timeit(#()method2(F,P))
function F = method1(F,P)
ind = (1:size(F,1)) + (P(:).'-1)*size(F,1); % create linear index
F(ind) = ~F(ind); % negate those entries
end
function F = method2(F,P)
for ii = 1:numel(P)
F(ii,P(ii)) = ~F(ii,P(ii));
end
end
Timings are 0.0065 s for Luis' answer, and 0.0023 s for the loop (MATLAB Online R2019a).
It is especially true for very large arrays, that loops are faster than vectorized code, if the vectorization requires creating an intermediate array. Memory access is expensive, using more of it makes the code slower.
Lessons: don't dismiss loops, don't prematurely try to optimize, and don't optimize without comparing.
Another solution:
xor( F, 1:7 == P )
Explanation:
1:7 == P generates one-hot arrays.
xor will cause a bit to retain its value against a 0, and flip it against a 1
Not sure if it qualifies as wizardry, but linear indexing does exactly what you want:
F = [0 0 0 1 0 1 1; 0 0 0 1 1 0 1; 1 1 0 1 1 0 0; 0 0 0 0 1 1 0; 1 1 1 0 0 0 0];
P = [4; 3; 6; 1; 7];
ind = (1:size(F,1)) + (P(:).'-1)*size(F,1); % create linear index
F(ind) = ~F(ind); % negate those entries

Filling a row and columns of a ndarray with a loop

I'm starting with Python and I have a basic question with "for" loop
I have two array which contains a values of a same variables:
A = data_lac[:,0]
In the first array, I have values of area and in the second on, values of mean depth.
I would like to find a way to automatize my calculation with different value of a parameter. The equation is the following one:
g= (np.sqrt(A/pi))/n
Here I can calculte my "g" for each row. Now I want to have a loop with differents values of "n". I did this:
i=0
while i <= len(A)-1:
for n in range(2,6):
g[i] = (np.sqrt(A[i]/pi))/n
i += 1
break
In this case, I just have one column with the calculation for n = 2 but not the following one. I tried to add a second dimension to my array but I have an error message saying that I have too many indices for array.
In other, I would like this array:
g[len(A),5]
g has 5 columns each one calculating with a different "n"
Any tips would be very helpful,
Thanks
Update of the code:
data_lac=np.zeros((106,7))
data_lac[:,0:2]=np.loadtxt("/home...", delimiter=';', skiprows=1, usecols=(0,1))
data_lac[:,1]=data_lac[:,1]*0.001
#Initialisation
A = data_lac[:,0]
#example for A with 4 elements
A=[2.1, 32.0, 4.6, 25]
g = np.zeros((len(A),))
I believe you share the indexes within both loops. You were increasing the i (index for the upper while loop) inside the inner for loop (which index with n).
I guess you have A (1 dim array) and you want to produce G (2 dim array) with size of (Len(A, 5))
I am not sure I'm fully understand your require output but I believe you want something like:
i=0
while i <= len(A)-1:
for n in range(2,6):
g[i][n-2] = (np.sqrt(A[i]/pi))/n # n-2 is to get first index as 0 and last as 4
i += 1 # notice the increace of the i is for the upper while loop
break
Important - remember that in python indentation means a lot -> so make sure the i +=1 is under the while scope and not indent to be inside the for loop
Notice - G definition should be as:
g = np.zeros((len(A),4), dtype=float)
The way you define it (without the 4) cause it to be 1 dim array and not 2-dim

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.

Dynamically creating and naming an array

Consider the following code snippet
for i = 1:100
Yi= x(i:i + 3); % i in Yi is not an index but subscript,
% x is some array having sufficient values
i = i + 3
end
Basically I want that each time the for loop runs the subscript changes from 1 to 2, 3, ..., 100. SO in effect after 100 iterations I will be having 100 arrays, starting with Y1 to Y100.
What could be the simplest way to implement this in MATLAB?
UPDATE
This is to be run 15 times
Y1 = 64;
fft_x = 2 * abs(Y1(5));
For simplicity I have taken constant inputs.
Now I am trying to use cell based on Marc's answer:
Y1 = cell(15,1);
fft_x = cell(15,1);
for i = 1:15
Y1{i,1} = 64;
fft_x{i,1} = 2 * abs(Y1(5));
end
I think I need to do some changes in abs(). Please suggest.
It is impossible to make variably-named variables in matlab. The common solution is to use a cell array for Y:
Y=cell(100,1);
for i =1:100
Y{i,1}= x(i:i+3);
i=i+3;
end
Note that the line i=i+3 inside the for-loop has no effect. You can just remove it.
Y=cell(100,1);
for i =1:100
Y{i,1}= x(i:i+3);
end
It is possible to make variably-named variables in matlab. If you really want this do something like this:
for i = 1:4:100
eval(['Y', num2str((i+3)/4), '=x(i:i+3);']);
end
How you organize your indexing depends on what you plan to do with x of course...
Yes, you can dynamically name variables. However, it's almost never a good idea and there are much better/safer/faster alternatives, e.g. cell arrays as demonstrated by #Marc Claesen.
Look at the assignin function (and the related eval). You could do what asked for with:
for i = 1:100
assignin('caller',['Y' int2str(i)],rand(1,i))
end
Another related function is genvarname. Don't use these unless you really need them.

Resources