I've taken an Algorithm course in which the instructor has decided to use Ada as programming language tool to test our understanding. The argument was that ADA language is quite close to the Pseudo code that appears in CLRS book.
Below code is a snip for Selection sort in ADA:
procedure Selection_Sort(Data : in out List) is
begin
for Destination_Index in Data'Range loop
for Source_Index in Destination_Index + 1 .. Data'Last loop
if Data(Source_Index) < Data(Destination_Index) then
Swap(Data, Source_Index, Destination_Index);
end if;
end loop;
end loop;
end Selection_Sort;
The following:
for Source_Index in Destination_Index + 1 .. Data'Last loop
will cause traversing the array from given element (Data1) to last element, however if I wish to traverse from the last element to the first, the following don't seem to work.
for Source_Index in Data'Last .. Data'First loop
It would be great help if someone can help me with this trivial problem, so that I can get on with the main problem at hand, which is learning Algorithms.
A range A .. B having A > B results in an empty range. In respect to the for cycle, there's the reverse keyword to define a descending loop (end of ARM 5.5 (9)). Hence reverse A .. B, where A < B, will result in looping from B down to A.
The rest is left up to you for the sake of learning. In order to learn something, you cannot avoid learning at the first place.
Related
Foreword
The Fortran program that I'm writing should deal with 1D, 2D and 3D problems depending on ndims, which can be 1, 2 or 3 and is read from an input file.
In these cases the quantity/ies of interest can be stored in arrays (one could be named phi)
of rank dims (ALLOCATABLE(:) or ALLOCATABLE(:,:) or ALLOCATABLE(:,:,:)),
or in arrays of rank 3 (ALLOCATABLE(:,:,:) with third dimension to be set equal to 1 in 2D or both second and third dimensions equal to 1 in 1D);
both cases are explained well in this answer. The first approach seems more elegant to me, but in the following I assume the second one, which is definitely simpler.
These quantities have to be operated on by several subroutines (e.g. mysub) along the ndims dimensions (along "pencils" should give a graphic idea), so I should call something like
SELECT CASE (ndims)
! 3D case
CASE (3)
DO j = ...
DO k = ...
CALL mysub(phi(:,j,k))
END DO
END DO
DO i = ...
DO k = ...
CALL mysub(phi(i,:,k))
END DO
END DO
DO i = ...
DO j = ...
CALL mysub(phi(i,j,:))
END DO
END DO
! 2D case
CASE (2)
DO j = ...
DO k = ...
CALL mysub(phi(:,j,1))
END DO
END DO
DO i = ...
DO k = ...
CALL mysub(phi(i,:,1))
END DO
END DO
! 1D case
CASE (1)
DO j = ...
DO k = ...
CALL mysub(phi(:,1,1))
END DO
END DO
END SELECT
Actual question
Can anyone suggest me (or help me to to devise!) a different way of store phi (maybe involving derived data types?) so that I can collapse the preceding code as follows?
DO id = 1, ndims
CALL mysub2(phi,id)
END DO
(Here mysub2 acts on mysub's place.)
So the question is how should I store phi, so that I can substitute the first code with the second one?
Maybe I could return to the foreword and decide to follow the point 1., in which case would be easier to write a generic interface. This would be, I think, just a way to "hide" exactly what the SELECT CASE would do. Which of the two (SELECT CASE/generic INTERFACE) would be more efficient?
Are these the only two ways to face this problem?
Perhaps I have misunderstood, but I think the answer to the specific question is to not make any changes to the storage or declaration of phi at all.
In the original code, three dimensional data (differentiating rank of the data from rank of the array used to store the data) is processed in slices along the first dimension, then the second, then the third. Two dimensional data is processed along the first, then the second, and one dimensional data is processed along the first only.
So with id going from 1 to the number of dimensions in the data, consider the following implementation of mysub2:
SUBROUTINE mysub2(phi, id)
TYPE(pink_elephant), INTENT(IN) :: phi(:,:,:)
INTEGER, INTENT(IN) :: id
INTEGER :: i, j, k
SELECT CASE (id)
CASE (1)
DO j = ...
DO k = ...
CALL mysub(phi(:,j,k))
END DO
END DO
CASE (2)
DO i = ...
DO k = ...
CALL mysub(phi(i,:,k))
END DO
END DO
CASE (3)
DO i = ...
DO j = ...
CALL mysub(phi(i,j,:))
END DO
END DO
END SELECT
END SUBROUTINE mysub2
~~
Generic interfaces can always be resolved at "compile time" - the specific procedure (not type bound) or binding (type bound) that will be invoked by a particular CALL statement or function reference can be determined just from looking at the declarations in the code.
If you have a situation where "runtime" information is going to affect the choice of procedure, then there has to be some other executable mechanism, other than or additional to the resolution of a generic, that comes into play - if statement, select case, dynamic dispatch, etc, etc, etc.
Asking whether generic resolution is more efficient than a executable decision is therefore not particularly meaningful - they are different things.
You probably want something like this:
program test
integer :: j,ndims
integer :: n ! rank of each dimension, could also be read from input an allocated separately
type arr
real(8) :: x(n) ! one array for each dimension
end type
type(arr),allocatable :: phi
read(*,*) ndims
allocate(phi(ndims))
do j=1,ndims
call mysub(phi(j)%x) ! acts on the array in dimension j
end do
contains
subroutine mysub(x)
...
end subroutine
end program
I learning more and more about Erlang language and have recently faced some problem. I read about foldl(Fun, Acc0, List) -> Acc1 function. I used learnyousomeerlang.com tutorial and there was an example (example is about Reverse Polish Notation Calculator in Erlang):
%function that deletes all whitspaces and also execute
rpn(L) when is_list(L) ->
[Res] = lists:foldl(fun rpn/2, [], string:tokens(L," ")),
Res.
%function that converts string to integer or floating poitn value
read(N) ->
case string:to_float(N) of
%returning {error, no_float} where there is no float avaiable
{error,no_float} -> list_to_integer(N);
{F,_} -> F
end.
%rpn managing all actions
rpn("+",[N1,N2|S]) -> [N2+N1|S];
rpn("-", [N1,N2|S]) -> [N2-N1|S];
rpn("*", [N1,N2|S]) -> [N2*N1|S];
rpn("/", [N1,N2|S]) -> [N2/N1|S];
rpn("^", [N1,N2|S]) -> [math:pow(N2,N1)|S];
rpn("ln", [N|S]) -> [math:log(N)|S];
rpn("log10", [N|S]) -> [math:log10(N)|S];
rpn(X, Stack) -> [read(X) | Stack].
As far as I understand lists:foldl executes rpn/2 on every element on list. But this is as far as I can understand this function. I read the documentation but it does not help me a lot. Can someone explain me how lists:foldl works?
Let's say we want to add a list of numbers together:
1 + 2 + 3 + 4.
This is a pretty normal way to write it. But I wrote "add a list of numbers together", not "write numbers with pluses between them". There is something fundamentally different between the way I expressed the operation in prose and the mathematical notation I used. We do this because we know it is an equivalent notation for addition (because it is commutative), and in our heads it reduces immediately to:
3 + 7.
and then
10.
So what's the big deal? The problem is that we have no way of understanding the idea of summation from this example. What if instead I had written "Start with 0, then take one element from the list at a time and add it to the starting value as a running sum"? This is actually what summation is about, and it's not arbitrarily deciding which two things to add first until the equation is reduced.
sum(List) -> sum(List, 0).
sum([], A) -> A;
sum([H|T], A) -> sum(T, H + A).
If you're with me so far, then you're ready to understand folds.
There is a problem with the function above; it is too specific. It braids three ideas together without specifying any independently:
iteration
accumulation
addition
It is easy to miss the difference between iteration and accumulation because most of the time we never give this a second thought. Most languages accidentally encourage us to miss the difference, actually, by having the same storage location change its value each iteration of a similar function.
It is easy to miss the independence of addition merely because of the way it is written in this example because "+" looks like an "operation", not a function.
What if I had said "Start with 1, then take one element from the list at a time and multiply it by the running value"? We would still be doing the list processing in exactly the same way, but with two examples to compare it is pretty clear that multiplication and addition are the only difference between the two:
prod(List) -> prod(List, 1).
prod([], A) -> A;
prod([H|T], A) -> prod(T, H * A).
This is exactly the same flow of execution but for the inner operation and the starting value of the accumulator.
So let's make the addition and multiplication bits into functions, so we can pull that part of the pattern out:
add(A, B) -> A + B.
mult(A, B) -> A * B.
How could we write the list operation on its own? We need to pass a function in -- addition or multiplication -- and have it operate over the values. Also, we have to pay attention to the identity of the type and operation of things we are operating on or else we will screw up the magic that is value aggregation. "add(0, X)" always returns X, so this idea (0 + Foo) is the addition identity operation. In multiplication the identity operation is to multiply by 1. So we must start our accumulator at 0 for addition and 1 for multiplication (and for building lists an empty list, and so on). So we can't write the function with an accumulator value built-in, because it will only be correct for some type+operation pairs.
So this means to write a fold we need to have a list argument, a function to do things argument, and an accumulator argument, like so:
fold([], _, Accumulator) ->
Accumulator;
fold([H|T], Operation, Accumulator) ->
fold(T, Operation, Operation(H, Accumulator)).
With this definition we can now write sum/1 using this more general pattern:
fsum(List) -> fold(List, fun add/2, 0).
And prod/1 also:
fprod(List) -> fold(List, fun prod/2, 1).
And they are functionally identical to the one we wrote above, but the notation is more clear and we don't have to write a bunch of recursive details that tangle the idea of iteration with the idea of accumulation with the idea of some specific operation like multiplication or addition.
In the case of the RPN calculator the idea of aggregate list operations is combined with the concept of selective dispatch (picking an operation to perform based on what symbol is encountered/matched). The RPN example is relatively simple and small (you can fit all the code in your head at once, it's just a few lines), but until you get used to functional paradigms the process it manifests can make your head hurt. In functional programming a tiny amount of code can create an arbitrarily complex process of unpredictable (or even evolving!) behavior, based just on list operations and selective dispatch; this is very different from the conditional checks, input validation and procedural checking techniques used in other paradigms more common today. Analyzing such behavior is greatly assisted by single assignment and recursive notation, because each iteration is a conceptually independent slice of time which can be contemplated in isolation of the rest of the system. I'm talking a little ahead of the basic question, but this is a core idea you may wish to contemplate as you consider why we like to use operations like folds and recursive notations instead of procedural, multiple-assignment loops.
I hope this helped more than confused.
First, you have to remember haw works rpn. If you want to execute the following operation: 2 * (3 + 5), you will feed the function with the input: "3 5 + 2 *". This was useful at a time where you had 25 step to enter a program :o)
the first function called simply split this character list into element:
1> string:tokens("3 5 + 2 *"," ").
["3","5","+","2","*"]
2>
then it processes the lists:foldl/3. for each element of this list, rpn/2 is called with the head of the input list and the current accumulator, and return a new accumulator. lets go step by step:
Step head accumulator matched rpn/2 return value
1 "3" [] rpn(X, Stack) -> [read(X) | Stack]. [3]
2 "5" [3] rpn(X, Stack) -> [read(X) | Stack]. [5,3]
3 "+" [5,3] rpn("+", [N1,N2|S]) -> [N2+N1|S]; [8]
4 "2" [8] rpn(X, Stack) -> [read(X) | Stack]. [2,8]
5 "*" [2,8] rpn("*",[N1,N2|S]) -> [N2*N1|S]; [16]
At the end, lists:foldl/3 returns [16] which matches to [R], and though rpn/1 returns R = 16
Given a very simple SPARK function that sums an array of integers:
function Add (X, Y : in Ints) return Ints is
Sum : Ints;
begin
for i in Ints'Range loop
pragma Loop_Invariant (for all j in Ints'First .. i - 1 => Sum(j) = X(j) + Y(j)); -- line 7
Sum(i) := X(i) + Y(i);
end loop;
return Sum; -- line 11
end Add;
(Where type Ints is array (Integer range 0 .. 9) of Integer_32)
Compiling without the loop invariant works fine (because I have a precondition that bounds the elements of X and Y such that overflow cannot occur). However, I need the invariant in order to show some properties of the post condition, but it results in:
7:69: warning: "Sum" may be referenced before it has a value
Phase 2 of 3: analysis and translation to intermediate language ...
7:10: "Sum" is not initialized
11:7: warning: "Sum" might not be initialized
I'm not sure how the concept of "being initialised" is expressed in the proof language so I don't know how to convince gnatprove that no uninitialised reads are occuring.
I can remove the warnings by explicitly setting all the elements of Sum to zero at the start of the function but I'm hoping that there's a better way.
In SPARK, arrays are considered as entire objects, and a component-by-component initialization like you do is not allowed. However, there is a heuristics in gnatprove which allows a simple for-loop over the range of the array, as you do. This is why without a loop invariant, you don't get the warning. This heuristics breaks down with the loop invariant, that's why you get the warning again.
You will have to accept the warning using pragma Warnings, as described here:
https://gcc.gnu.org/onlinedocs/gnat_rm/Pragma-Warnings.html
And to avoid the error you are getting at line 7, you may move the loop invariant after the assignment (and change the range of the quantificaton accordingly).
I am trying to change the value of upper bound in For loop ,but the Loop is running till the upper bound which was defined in the starting.
According to logic loop should go infinite, since value of v_num is always one ahead of i,But loop is executing three time.Please explain
This is the code
DECLARE
v_num number:=3;
BEGIN
FOR i IN 1..v_num LOOP
v_num:=v_num+1;
DBMS_OUTPUT.PUT_LINE(i ||' '||v_num);
END LOOP;
END;
Ouput Coming
1 4
2 5
3 6
This behavior is as specified in the documentation:
FOR-LOOP
...
The range is evaluated when the FOR loop is first entered and is never re-evaluated.
(Oracle Documentation)
Generally, FOR loops would be fixed iterations
For indeterminate looping, use WHILE
This isn't Oracle specific, and why there are separate looping constructs.
While it is generally considered a bad idea to change the loop variable's value, sometimes it seems like the only way to go. However, you might find that loops are optimized, and that might be what is happening here.
There's nothing preventing the language designers from saying "The upper bound of the for loop is evaluated only once". This appears to be the rule that plsql is following here.
I'm trying to learn Ada for a course at the University, and I'm having a lot of problems wrapping my head around some of the ideas in it.
My current stumbling block: Let's say I have a function which takes a Matrix (just a 2-dimensional array of Integers), and returns a new, smaller matrix (strips out the first row and first column).
I declare the matrix and function like this:
type MATRIX is array(INTEGER range <>, INTEGER range <>) of INTEGER;
function RemoveFirstRowCol (InMatrix: in MATRIX) return MATRIX is
Then I decide on the size of the Matrix to return:
Result_matrix: MATRIX (InMatrix'First(1) .. InMatrix'Length(1) - 1, InMatrix'First(2) .. InMatrix'Length(2) - 1);
Then I do the calculations and return the Result_matrix.
So here's my problem: when running this, I discovered that if I try to return the result of this function into anything that's not a Matrix declared with the exact proper size, I get an exception at runtime.
My question is, am I doing this right? It seems to me like I shouldn't have to know ahead of time what the function will return in terms of size. Even with a declared Matrix bigger than the one I get back, I still get an error. Then again, the whole idea of Ada is strong typing, so maybe this makes sense (I should know exactly the return type).
Anyways, am I doing this correctly, and is there really no way to use this function without knowing in advance the size of the returned matrix?
Thanks,
Edan
You don't need to know the size of the returned matrix in advance, nor do you need to use an access (pointer) type. Just invoke your function in the declarative part of a unit or block and the bounds will be set automatically:
procedure Call_The_Matrix_Reduction_Function (Rows, Cols : Integer) is
Source_Matrix : Matrix(1 .. Rows, 1 .. Cols);
begin
-- Populate the source matrix
-- ...
declare
Result : Matrix := RemoveFirstRowCol (Source_Matrix)
-- Result matrix is automatically sized, can also be declared constant
-- if appropriate.
begin
-- Process the result matrix
-- ...
end;
end Call_The_Matrix_Reduction_Function;
Caveat: Since the result matrix is being allocated on the stack, you could have a problem if the numbers of rows and columns are large.
Because your MATRIX type is declared with unbound indexes, the type is incomplete. This means that it can be returned by a function. In this case, this acts as it were pointer. Of course the compiler does not know the exact indexes in compile time, the result matrix will always be allocated in heap.
Your solution should be working. The only problem is when you create the result matrix is, that it will work only if the original matrix index starts with 0.
m:MATRIX(11..15,11..20);
In this case m'first(1) is 11, m'length(1) is 5! So you get:
Result_matrix:MATRIX(11..4,11..9);
which is CONSTRAINT_ERROR...
Use the last attribute instead. Even if you usually use with 0 index.
But remember, you do not need to use pointer to the MATRIX because the MATRIX is also incomplete, and that's why it can be used to be returned by a function.
The caller knows the dimensions of the matrix it passes to your function, so the caller can define the type of the variable it stores the function's return value in in terms of those dimensions. Does that really not work?
your function cannot know the size of the result matrix in compile time
you need to return a pointer to the new matrix :
type Matrix is array (Positive range <>, Positive range <>) of Integer;
type Matrix_Ptr is access Matrix;
-- chop the 1'th row and column
function Chopmatrix (
Inputmatrix : in Matrix )
return Matrix_Ptr is
Returnmatrixptr : Matrix_Ptr;
begin
-- create a new matrix with is one row and column smaller
Returnmatrixptr := new Matrix(2 .. Inputmatrix'Last, 2.. Inputmatrix'Last(2) );
for Row in Inputmatrix'First+1 .. Inputmatrix'Last loop
for Col in Inputmatrix'First+1 .. Inputmatrix'Last(2) loop
Returnmatrixptr.All(Row,Col) := Inputmatrix(Row,Col);
end loop;
end loop;
return Returnmatrixptr;
end Chopmatrix ;