Implamenting Dikstra in Fortran
Since I am going into this knowing next to nothing about fortran please do excuse any awfull mistakes, I may include a coraspondance email at some point, and if I do, feel free to send any corrections to there. This page also assumes a base level knowlage of programing, I am not going to explain in detail the concept of a for loop and expect that you should be able to recognise what a fortran for loop does from looking at it, ( i mean, it is litterally:
INTEGER :: I
DO I = 1,5
PRINT "(1I1)",I
END DO
so not particularly complicated, (though, granted, it isn’t actually called a for loop cause this language was made by some chaps from the US in the 50s close enough to the CIA to be invited to all the internal LSD parties (YK, back when engineers got into some really interesting stuff, just look up Jack Parsons, the 50s really was a time))), the funky print statement just means 1 integer of 1 digit to be prined, there are other types of course and strings just print as usual, I’ll include a table at some point that fully explains this. Its a bit more of a pain in the ass than the C printf statement but to my mind at least is far more readble than the interesting std::print << gumpf that C++ has going on. And we do not speak of python here, or other languages, esspecially not bloody java (if you mention javascript god rest your soul). except for if i post anything in these languages cause i am somewhat required to use them for my course. suffice to say, i rather like the python and java print statements.
|A brief intro to Dikstras Shortest Path 20/11/24
As described Dikstra first creates a set of all the unviseted edges in a given graph. It then asignes each of these nodes a distance from the starting node. For the starting node itself this value is 0, for all other is is infinate as no path is currently known.
From the set of unvisited edges the algorithem will now select the node with the smallest distance. This will invariably at the start be the root node.
Now, for the selected edges ending node look at all of its edges and calculate the distances from the root node through them to thier target node, so adding the distance marker on the current node to the distance of the edge being checked. Then, if the calculated value for any of said nodes is lower than the stored value of distance from the root node, update the stored edge to that node with the current edge and calculated distance.e.g
You are at Node C, it is marked with a value of distance 5 from the root node, it is connected to D and E. The distance from C to D is 3 and D to E is 20. the calculated distances from root to D and E through C are therefore 8 and 25 respectively. The shortest routes from root to D and E respectively are 9 and 5 therefore comparing the route through C to the stored roots the root through C to D is 8 and that is updated to be the smallest value, the route to E through C is ignored as it is larger than the stored value for from root to E.
Pseudocode:
for edges connected to C
if C + edge distance < stored distance to node
stored edge to C = edge
Once this has been done the curent edge is marked as visited as all of the shortest paths from the root node to other nodes through it have been checked and set to thier lowest possible values.
Pseudocode: note, Source Node is the node from which you want to calculate paths
new MinPriorityQue edges to check
new List CheckedNodes
Edges to check = SourceEdge
While NextEdge.dist is not MaxInt:
NextEdge = NodesToCheck.Min()
For edges in NextEdge.TargetNode.ConnectedEdges:
if edge.dist < EdgestoCheck dist to edge target node
Edges to Check(edge.target node) = edge
# The edge for the target node in edges to check is updated with the new node
EndFor
EndWhile
CheckedNodes.append(NodesToCheck.Min())
NodesToCheck.DeleteMin()
once this is done we simply follow the reverse path from the desired node to the source node by going to the target node and following the edges in reverse.
The Fortran Bit
The fist things I feel aught to be mentioned about fortran are these points
- that array indexes start at 1.
- all variables must be declared IMIDIATELY after the the begining og the program but after use statements (the equivalent in fortran to import)
- ALLWAYS put IMPLICIT NONE at the start of programs and the like, just do it
functions and subroutines 20/11/24
Functions and subroutines are fundamentally rather different in fortran, a function will allways return a value whereas a subroutine will only perform a set of actions on passed values. here are two examples, one of each, each calculating the average of three values
Function
PROGRAM MAIN
INTEGER :: AVERAGE, RESULT
RESULT = AVERAGE (1,2,3)
END PROGRAM MAIN
FUNCTION AVERAGE(A,B,C)
INTEGER::A,B,C
AVERAGE = A+B+C/3
RETURN
END FUNCTION AVERAGE
subroutine
PROGRAM MAIN
INTEGER :: RESULT
CALL AVERAGE (1,2,3,RESULT)
END PROGRAM MAIN
SUBROUTINE AVERAGE(A,B,C,RESULT)
INTEGER::A,B,C,RESULT
RESULT = A+B+C/3
RETURN
END SUBROUTINE AVERAGE
As you can see, a function will return the value average and set result to said value, whereas a subroutine performs an operation on the values it has been passed, essentially like passing by referance in C or C++ if that analogy makes a single lick of sense.
Write and Print 26/11/24
In fortran there are two methods of outputing, so far i have been using the print command, but now i have learned of the Write command, a far superior method of output in my humble opinion.
The simplest form of print is:
PRINT *, VAR1,VAR2,VAR3
This will consecutively print out the three given vars on the same line. This is usefull for simple writing to the command line but somewhat more granular controll can be gained by using format specification, the format of which is:
PRINT "(<format>)",VAR1,VAR2,VAR3
Write
The simplest form of Write is:
WRITE (*,*) VAR1,VAR2,VAR3
And the formated version is:
WRITE (*,"(<format>)") VAR1,VAR2,VAR3
Write can also output multiple write statements to the same line by doing this:
WRITE (*,"(<format>)",ADVANCE = NO) VAR1,VAR2,VAR3
<Format> Compasition
Charachter | Use | Example |
I | Integer, in the form of (<count>I<charachters>.<min chars>) this means that for the example it will display 3 variables that are integers, showing a max of 4 charachters and a minimum of 2 | PRINT “(3I4.2)”,VAR1,VAR2,VAR3 |
F | Identical to I but for the Real variable type | PRINT “(3F4.2)”,VAR1,VAR2,VAR3 |
E | Identical to I but for the exponent variable type | PRINT “(3E4.2)”,VAR1,VAR2,VAR3 |
ES | Identical to I but for scientific notation output | PRINT “(3ES4.2)”,VAR1,VAR2,VAR3 |
A | Identical to I but for chars and strings (will output strings up to 4 chars in this example) | PRINT “(3A4)”,VAR1,VAR2,VAR3 |
X | Used to output spaces in the form NX where N is the ammount of spaces | PRINT “(10X)” |
/ | forces the next output to a new line (Example outputs VAR3 onto new line | PRINT “(2F4.2,/1F4.2)”,VAR1,VAR2,VAR3 |
End Report.
I will probably further update this page with what I have learnt from this progect surrounding fortran and the like but will simply include the final report here to show what I have done in the mean time. Honestly I am kinda burned out on this right now, it was a large progect to do in a completely new language, especially a language as non-standard to modern programing as FORTRAN, as such it may be a while before this page is updated. (current date is the 24th of december in the year 2024 for referance, merry christmass I guess.)
k, so, it will be uploaded once marked so to ensure plagerisim bots dont take my very soul.
Published @ 19/11/2024 4:36 pm