You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Note that we can also use `AIGraphNonWeightedFixtureStructure` for a weighted graph in case we do not want the edge weights to be drawn.
228
+

229
+
230
+
In case of visualizing a weighted graph, each edge weight is rendered in the inner middle of the edge arrow like in Figure *@edgelabels@*. You might want to move the edge labels for better readability, e.g. if you need the graph for a presentation.
231
+
In such a case, you can export it to SVG like in this example:
232
+
233
+
```
234
+
RSSVGCairoExporter new
235
+
canvas: AIWeightedDAGFixture new weightedDAG buildGraphCanvas;
236
+
exportToFile: 'c:/temp/foo.svg' asFileReference
237
+
```
238
+
239
+
Then you can keep working on it with your favorite SVG editor.
240
+
241
+
`RSSVGCairoExporter` and other Roassal exporters can be loaded by executing this code snippet:
## Topological sortingLet us start with our first algorithm: a topological sort.A topological sort makes that a node is treated before the nodes that depend on it are treated.If you consider tasks, it means that you want to do first a task before doing the ones that depend on this one.Topological sorting is a way of ordering a **directed acyclic graph** such that for every directed edge $(U, V)$ fromnode $U$ to node $V$, $U$ becomes first in the resulting ordering.We present here one algorithm named Khan's algorithm.### ExampleThe topological sorting can be applied to a graph in which its nodes represents software dependencies.For example to install a library, there are some modules that need to be installed before others.So, in this case, a topological sort is useful to know which modules to install first \(the one that has no dependencies\) and so on.Now for a same graph multiple topological sorts are possible just because since we treat first the nodes having no dependenciestheir traversal order can be different and in addition the traversal order of their dependent can be different too. Figure *@soft@* shows one graph and one of the possible topological sort.### Kahn's algorithmTo apply a topological sort to a graph, the graph must be a directed acyclic graph \(DAG\). There is at least one topologicalpossible order for a DAG.The algorithm that is used in this library is the Kahn's algorithm.It has a time complexity of $O(V + E)$.The pseudocode taken from [https://en.wikipedia.org/wiki/Topological\_sorting](https://en.wikipedia.org/wiki/Topological_sorting) is the following one:```L ← Empty list that will contain the sorted elements
1
+
## Topological Sorting
2
+
3
+
Let us start with our first algorithm: a topological sort. A topological sort makes that a node is treated before the nodes that depend on it are treated. If you consider tasks, it means that you want to do first a task before doing the ones that depend on this one.
4
+
5
+
Topological sorting is a way of ordering a **directed acyclic graph** such that for every directed edge $(U, V)$ from node $U$ to node $V$, $U$ becomes first in the resulting ordering.
6
+
7
+
We present here one algorithm named Khan's algorithm.
8
+
9
+

10
+
11
+
### Example
12
+
13
+
The topological sorting can be applied to a graph in which its nodes represents software dependencies.
14
+
For example to install a library, there are some modules that need to be installed before others.
15
+
So, in this case, a topological sort is useful to know which modules to install first \(the one that has no dependencies\) and so on.
16
+
17
+
Now for a same graph multiple topological sorts are possible just because since we treat first the nodes having no dependencies
18
+
their traversal order can be different and in addition the traversal order of their dependent can be different too. Figure *@sort@* shows one graph and one of the possible topological sort.
19
+
20
+
### Kahn's algorithm
21
+
22
+
To apply a topological sort to a graph, the graph must be a directed acyclic graph \(DAG\). There is at least one topological possible order for a DAG.
23
+
24
+
The algorithm that is used in this library is the Kahn's algorithm.
25
+
It has a time complexity of $O(V + E)$.
26
+
The pseudocode{!footnote|taken from en.wikipedia.org\slash wiki\slash Topological\_sorting!} is the following one:
27
+
28
+
```
29
+
L ← Empty list that will contain the sorted elements
2
30
S ← Set of all nodes with no incoming edge
3
31
while S is not empty do
4
32
remove a node n from S
@@ -10,75 +38,153 @@ while S is not empty do
10
38
if graph has edges then
11
39
return error (graph is not a DAG)
12
40
else
13
-
return L (a topologically sorted order)```This algorithm is implemented in the class `AITopologicalSorting` subclass of `AIGraphAlgorithm`.The parent class \(`AIGraphAlgorithm`\) provides all the mechanisms to handle the implementation of thegraph data structure. `AITopologicalSorting` has the only responsibility: to implement the logic of the algorithm.The following proposes a first implementation```AITopologicalSorting >> run
41
+
return L (a topologically sorted order)
42
+
```
43
+
44
+
This algorithm is implemented in the class `AITopologicalSorting` subclass of `AIGraphAlgorithm`.
45
+
The parent class \(`AIGraphAlgorithm`\) provides all the mechanisms to handle the implementation of the
46
+
graph data structure. `AITopologicalSorting` has the only responsibility: to implement the logic of the algorithm.
ifTrue: [ Error signal: 'Not a DAG (Directed Acyclic Graph)' ].
37
75
38
76
"Return the topological order the first element being the node without any dependencies"
39
-
^ topologicalSortedElements```### Improving the implementationThe method `run` is a bit too long to our taste.The fact that we have to add comments to separate its code logic is a call to define separate methods.First we define two methods `initializeElements` and `gatherNoIncomingNodes`.And we express the algorithm by redefining the method `run` as follows:```AITopologicalSorting >> initializeElements
nodesWithNoIncomingEdges := LinkedList new```Note that `nodesWithNoIncomingEdge` uses a linked list because it hasa better time complexity for removing the first element.```AITopologicalSorting >> gatherNoIncomingNodes
43
-
"Obtain all the nodes without incoming nodes"
44
-
45
-
nodesWithNoIncomingEdges addAll:
46
-
(nodes select: [:node | node isLeaf ]).``````AITopologicalSorting >> run
Error signal: 'Not a DAG (Directed Acyclic Graph)' ].
73
-
^ topologicalSortedElements```Now the logic of the algorithm is clearer and at a nice level of abstraction.In addition we can focus on the structure of the algorithm, treated nodes are added one by one to the `topologicalSortedElements` collectionwhile dependents are added to the working list `nodesWithNoIncomingEdges`.And the algorithm iterates until the working list gets empty.### Case studyImage that the graph shown in Figure *@soft@* represents software dependencies. You want to install the module _G_. But, to installthat module you must install all the other ones before in a topological order. You need to install module _C_ and _A_ before installingmodule _D_. So in this case the topological sorting is the algorithm that we need to solve the problem.To solve this problem programatically we only need to declare the nodes, the edges and the run the algorithm.```"First define the nodes and the edges"
77
+
^ topologicalSortedElements
78
+
```
79
+
80
+
### Improving the implementation
81
+
82
+
The method `run` is a bit too long to our taste.
83
+
The fact that we have to add comments to separate its code logic is a call to define separate methods.
84
+
85
+
First we define two methods `initializeElements` and `gatherNoIncomingNodes`.
86
+
And we express the algorithm by redefining the method `run` as follows:
topologicalSortedElements := topSortingAlgo run.```Note that a _DAG_ may have several topological orders which all of them are correct. If we look at the result we get theorder in which the software dependencies need to be installed.`#( $A $B $C $D $E $F $G )`### ConclusionTopological sorting is simple algorithm working with a working list, the list where we add the next nodes to be treated.It shows that the algorithm works until the list gets empty.This is the typical structure of iterating algorithms based on working list.
178
+
topologicalSortedElements := topSortingAlgo run.
179
+
```
180
+
181
+
Note that a _DAG_ may have several topological orders which all of them are correct. If we look at the result we get the
182
+
order in which the software dependencies need to be installed.
183
+
184
+
`#( $A $B $C $D $E $F $G )`
185
+
186
+
### Conclusion
187
+
188
+
Topological sorting is simple algorithm working with a working list, the list where we add the next nodes to be treated.
189
+
It shows that the algorithm works until the list gets empty.
190
+
This is the typical structure of iterating algorithms based on working list.
Copy file name to clipboardExpand all lines: Chapters/Chapter5/chapter5.md
+34-2Lines changed: 34 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
## Shortest Path
2
2
3
-
The Shortest Path problem consists on finding a path between two pairs of nodes in which the sum of the weights is minimized. For a general graph, this problem is NP-hard. For some kind of graphs, like trees or directed acyclic graphs, this problem can be solved in linear time.
3
+
The Shortest Path problem consists on finding a path between two pairs of nodes in which the sum of the weights is minimized. For a general graph, this problem is NP-hard. For some kind of graphs, like trees or other directed acyclic graphs, this problem can be solved in linear time.
4
4
5
5
In this chapter, we will present multiple algorithms to solve the shortest path problem, including case studies for some of them. Most of the algorithms find the solution for one single source to all other nodes. One finds the solution for a single source to a single sink, and one resolves the shortest path between all pairs of nodes. The following table is an overview of the algorithms.
6
6
@@ -171,7 +171,7 @@ The choice between BFS and DFS shortest path search depends on the structure of
171
171
172
172
### Dijkstra's algorithm
173
173
174
-
The Dijkstra's algorithm is one of the most-know algorithms for calculating the shortest path in a weighted graph. As BFS, this algorithm is also a single-source shortest path algorithm. In its naive implementation, it has a time complexity of $O(V^2)$. But, it can be optimized using a heap or a Fibonacci heap as a data structure to a time complexity of $O((V+E)*log V)$. If a Fibonacci heap is used we get the best possible time complexity $O(E + V * log V)$ possible \(at the moment\). Dijkstra's algorithm can handle a graph with cycles, but it cannot handle negative weights.
174
+
The Dijkstra's algorithm is one of the most-know algorithms for calculating the shortest path in a **nonnegative weighted graph**. As BFS, this algorithm is also a single-source shortest path algorithm. In its naive implementation, it has a time complexity of $O(V^2)$. But, it can be optimized using a heap or a Fibonacci heap as a data structure to a time complexity of $O((V+E)*log V)$. If a Fibonacci heap is used we get the best possible time complexity $O(E + V * log V)$ possible \(at the moment\). Dijkstra's algorithm can handle a graph with cycles, but it cannot handle negative weights.
175
175
176
176
The algorithm idea is:
177
177
@@ -588,6 +588,38 @@ pathFrom: sourceModel to: destinationModel
588
588
589
589
We see that the method is able to recognize disturbances derived from any negative cycle.
590
590
591
+
### Shortest path in an undirected graph
592
+
593
+
Excepting the algorithm for finding the shortest path in a DAG, the rest of the algorithms presented here are able to find the shortest path not only in directed but also in undirected graphs. As a matter of fact, any undirected graph is also a directed graph. You just have to specify any edges $\{u, v\}$ twice $u \to v$ and $v \to u$.
Note that each undirected edge is represented by two corresponding directed edges.
620
+
621
+
However, there is a restriction in case of negative weights, since by doubling an undirected negative edge with two directed edges, the Bellman-Ford or the Floyd-Warshall algorithm would detect a negative cycle.
622
+
591
623
### Longest path problem
592
624
593
625
To calculate the longest path of a directed graph, we can simply multiply all the edge weights by $-1$ and then calculate the shortest path.
0 commit comments