I have a loop that internally unrolls a sparse matrix vector multiplication. We calculate this using a diagonal approach for the upper right matrix with leads to a different length for each diagonal.
The unrolling then happens linewise, i.e. I calculate several diagonals at once, until the shortest diagonal reaches the end of the matrix. Then I want to calculate the remaining diagonals with another loop with decreased unrolling length.
This leads to the problem that the second loop needs to start where the first loop has ended. I'm now stumbling upon a construct like the following (very simplified):
do diag=1, nDiagonals-3, 4
! here be dragons
end do
do diag=diag, nDiagonals-2, 3
! here be smaller dragons
end do
In Fortran the do index has to be set in the control clause, in contrast to C where for(;n<m;==n) is a possible loop control clause. But is the construct above with do index=index, upperbound valid? Or are there better approaches for this kind of loop index handling?
I can't see anything syntactically wrong with your code, nor do I think you are doing anything dangerous if legal.
After the end of the first loop diag will have the value it would have if the loop continued for one more iteration. This behaviour is defined by the standard. Given the snippet
do diag = start, stop, stride
! do stuff
end do
at the end of the loop diag has value equal to (start + n*stride) where n is the smallest integer such that (start + n*stride)>stop
So, for a loop such as
do diag = 1,10,3
! do stuff
end do
! now diag == 13
and you can carry on using it to start the next loop as you outline.
What you can't do, in Fortran, is adjust the value of the do-variable inside the loop, the compiler behaves as if it establishes the loop limits at the first encounter with the do statement.
Related
Similar questions have been asked and the general consensus is that anything can be converted from recursion to for loops and vice versa. However, I can't find a way to convert a function of the following pseudocode type to a for loop:
def recursive(n):
if n == 0:
return
for i in range(some_number):
do_sth...
recursive(n-1)
In this case, there is n nested loops and n varies depending on the given argument. When using only for loops, the number of nested loops seems to be always predetermined in the code, it doesn't vary depending on "input". Is there a way to make something like this using only for loops?
Is there a way to make something like this using only for loops?
Well, if you admit a while loop as a case of a pseudocode for loop, at least your example can be made:
def nonrecursive(n):
a = []
z = 0
while n:
while n:
i = z
if i == some_number: break
print((n, i))
a += [[n, i]]
n -= 1
z = 0
if not a: break
n, i = a.pop()
i += 1
z = i
We need to be careful here.
The general true statement is that loops can replace recursion and vice versa. This can be shown lots of ways; see the structured programming theorem for ideas.
Whether for loops can replace recursion depends upon your definitions. Can your for loops run forever, or for an indefinite amount of time not known in advance? If so, they are functionally equivalent to while loops, and they can replace recursion. If your for loops cannot be made to run forever or for an unknown (initially) number of iterations, recursion cannot always be replaced.
Really, it's while loops (plus a stack data structure) that can replace recursion without much trouble.
I am learning to compute the time complexity of algorithms.
Simple loops and nested loops can be compute but how can I compute if there are assignments inside the loop.
For example :
void f(int n){
int count=0;
for(int i=2;i<=n;i++){
if(i%2==0){
count++;
}
else{
i=(i-1)*i;
}
}
}
i = (i-1)*i affects how many times the loop will run. How can I compute the time complexity of this function?
As i * (i-1) is even all the time ((i * (i-1)) % 2 == 0), if the else part will be true for one time in the loop, i++ makes the i odd number. As result, after the first odd i in the loop, always the condition goes inside the else part.
Therefore, as after the first iteration, i will be equal to 3 which is odd and goes inside the else part, i will be increased by i * (i-1) + 1 in each iteration. Hence, if we denote the time complexity of the loop by T(n), we can write asymptotically: T(n) = T(\sqrt(n)) + 1. So, if n = 2^{2^k}, T(n) = k = log(log(n)).
There is no general rule to calculate the time complexity for such algorithms. You have to use your knowledge of mathematics to get the complexity.
For this particular algorithm, I would approach it like this.
Since initially i=2 and it is even, let's ignore that first iteration.
So I am only considering from i=3. From there I will always be odd.
Your expression i = (i-1)*i along with the i++ in the for loop finally evaluates to i = (i-1)*i+1
If you consider i=3 as 1st iteration and i(j) is the value of i in the jth iteration, then i(1)=3.
Also
i(j) = [i(j-1)]^2 - i(j-1) + 1
The above equation is called a recurrence relation and there are standard mathematical ways to solve it and get the value of i as a function of j. Sometimes it is possible to get and sometimes it might be very difficult or impossible. Frankly, I don't know how to solve this one.
But generally, we don't get situations where you need to go that far. In practical situations, I would just assume that the complexity is logarithmic because the value of i is increasing exponentially.
I want to compute the summation of odd numbers in a given range like 1 to 9 is the given input. and my program will show the summation of all odd numbers between 1 to 9. Though the task is so simple theoriticaly, but as a starter of turbo prolog, I can't handle the loop to compute the summation. Any help would be appreciating..
Advance thanks.
I'm not going to write the full solution for you, but can give an idea how to "loop" through a summation in a general way. Looping in Prolog is often done through recursion. The recursion gets around the fact that Prolog will not let you reinstantiate a variable within the same predicate clause once it's instantiated (unless you backtrack). The following is ISO Prolog syntax.
sum_values(First, Last, Sum) :-
sum_values(First, Last, 0, Sum).
sum_values(First, Last, Sum, Sum) :-
First > Last.
sum_values(First, Last, Acc, Sum) :-
First =< Last,
NewAcc is Acc + First,
NewFirst is First + 1,
sum_values(NewFirst, NewAcc, Sum).
The first clause sets up an accumulator starting at the value 0.
The second clause handles the normal recursive case where the first value does not exceed the last. The first value is added to the accumulator to create an updated accumulator, and the "first" value is incremented to create a new first value. The recursive call to sum_values computes the rest of the sum with the new accumulator.
The last (third) clause unifies the final sum with the accumulator when the first value finally exceeds the last.
Note that I could have implemented this without introducing the accumulator, but then I wouldn't have the tail recursion which can be optimized (if desired) by the Prolog system. The non-accumulator version looks like this:
sum_values(First, Last, 0) :- First > Last.
sum_values(First, Last, Sum) :-
First =< Last,
NewFirst is First + 1,
sum_values(NewFirst, Last, PartialSum),
Sum is PartialSum + First.
This is a little shorter, but there's no tail recursion that can be refactored.
Modifications you would need to make for your problem (these are ones I'm aware of, as I'm only a little familiar with some of TP's syntax):
Replace is/2 with =/2 (I think TP uses =/2 for expression evaluation)
You might have to replace =< with <= (I don't recall which one TP likes)
Check that First is odd. If it's not, you need to skip adding it to the accumulator.
You could also do an initial check for odd First and if it's not odd, increment it to form a new First, then proceed doing a summation incrementing by 2 through the recursion instead of by 1.
So I am relatively new to MatLab and I was assigned the task to find the average of all of the elements in the first or last rows and first or last columns in an array. My function is below:
function [ myavg ] = avg_outer( array_in )
%UNTITLED2 Summary of this function goes here
% Detailed explanation goes here
[rowsin, colin]=size(array_in);
sum=0;
numelement=0;
currentpos=1;
currentrow=1;
j=1;
while currentpos>1 && currentpos<rowsin
sum=sum+array_in(currentrow,1)+array_in(currentrow,colin);
numelement=numelement+2;
currentrow=currentrow+1;
if currentrow==1
for j=1:1:colin
sum=sum+array_in(currentrow,j);
numelement=numelement+1;
end
elseif currentrow==rowsin
sum=sum+array_in(currentrow,j);
numelement=numelement+1;
end
end
myavg=sum/numelement;
end
When I run the function with a random array, I am not getting a result.
Any help or idea on where I went wrong?
Assuming I read the problem statement correctly, you can just create a mask that is true around the border, false in the middle, and take the mean of the masked version of A.
function [out_avg] = avg_outer(A)
mask = true(size(A));
mask(2:end-1,2:end-1) = false;
out_avg = mean(A(mask));
I couldn't really follow the logic in your posted code to debug it, sorry. Hopefully this answer shows you some of the advantages of vectorizing Matlab code.
The right way to do this is as per the answer from #kmac. But specifically related to your looping code, there are multiple issues.
currentpos starts at 1, which means that the while loop is never entered because currentpos > 1 is false. This is why you are getting NaN as the answer.
Even after fixing the above, you never increment currentpos so the while loop would never be exited (or more correctly would execute until an out of bounds error occurs).
Even after fixing the above, the first time into the while loop (in the 3rd line of the loop) you make currentrow = currentrow + 1;, which will be 2, means that the subsequent if statement is always false, and you will not be summing the first row of the matrix.
Even if you fix the above, the for loop adds all elements of the first row, but you've already accounted for the first and last elements of this row, so you're adding them into the sum twice.
Even if you fix the above, when currentrow == rowsin, i.e. the last row, you don't have a for loop to do the actual summation of the elements of the row. Noting that you don't want the first and last element because you've already added them in.
Consider the following C code
int j,n; //declaration
j=1; //initialization
while(j<=n) //while loop
j=j*2; //code ends here
What is the number of comparisons made in the execution of the loop in the above code?
I have tried the following: let increment of j is pow(2,0), pow(2,1), pow(2,2), etc. For some value of i so according to the question
pow(2,i)<=n
i<=(log n/log2)
What after this? The answer is floor(log n/log 2)+1 but how?
That code is undefined, there is no answer since you don't specify the value of n and as the code is written there's no chance for n to have a well-defined value when the loop runs.
n is never initialised, so technically the behaviour is undefined as you're using an uninitialised variable in while (j<=n).
If you want to set n to the largest possible integer value, use
n = INT_MAX
Which is defined in the standard include file <limits.h>
But, that will result in integer overflow due to j=j*2 happening after the j<=n check. One way round this would be to define n = INT_MAX / 2. Better still use a do / while loop rather than while and perform the check at the end.
Assuming that you initialized the variable n with a proper value, as you know you are going to pow(2,i)<=n which means i<=log{2}n (just inverting the function).
log{base 2}n = log n/log2 for the well known logarithmic property.
Now the calculation is exact when i is real but in this case i is an integer you won't get exactly that number so the correct index will be in the approximation of [floor(logn/log2);floor(logn/log2)+1] which will be the loop required for for pow(2,i)<=n<pow(2,i+1)
Let's do a simple example:
n=11; ln(n)/ln(2)=2.39/0.69=3.46
floor(3.46) = 3
floor(3.46)+1 = 4
i=1 i<=n: true: i*=2
i=2 i<=n: true: i*=2
i=4 i<=n: true: i*=2
i=8 i<=n: true: i*=2
i=16 i<=n: false=> don't loop
which is exactly four
Let us assume some n values
For n=1 loop executes 1 time.
For n=2 loop executes 2 times.
For n=3 loop executes 2 times.
For n=(4 to 7) loop executes 3 times.
For n=8 loop executes 4 times.
So for n values like 1,2,4,8,16... loop executes 1,2,3,4,5...
Therefore if you compare these values mathematically -
For n=2^k loop executes (k+1) times from n=2^k, k=log2n (logn with base 2)
So loop executes log2n(floor value)+1 times.
yes code will end you are not initializing n. First initialize it then calculte