Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
197
Task/Dijkstras-algorithm/Clojure/dijkstras-algorithm.clj
Normal file
197
Task/Dijkstras-algorithm/Clojure/dijkstras-algorithm.clj
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
(declare neighbours
|
||||
process-neighbour
|
||||
prepare-costs
|
||||
get-next-node
|
||||
unwind-path
|
||||
all-shortest-paths)
|
||||
|
||||
|
||||
;; Main algorithm
|
||||
|
||||
|
||||
(defn dijkstra
|
||||
"Given two nodes A and B, and graph, finds shortest path from point A to point B.
|
||||
Given one node and graph, finds all shortest paths to all other nodes.
|
||||
|
||||
Graph example: {1 {2 7 3 9 6 14}
|
||||
2 {1 7 3 10 4 15}
|
||||
3 {1 9 2 10 4 11 6 2}
|
||||
4 {2 15 3 11 5 6}
|
||||
5 {6 9 4 6}
|
||||
6 {1 14 3 2 5 9}}
|
||||
^ ^ ^
|
||||
| | |
|
||||
node label | |
|
||||
neighbour label--- |
|
||||
edge cost------
|
||||
From example in Wikipedia: https://en.wikipedia.org/wiki/Dijkstra's_algorithm
|
||||
|
||||
Output example: [20 [1 3 6 5]]
|
||||
^ ^
|
||||
| |
|
||||
shortest path cost |
|
||||
shortest path---"
|
||||
([a b graph]
|
||||
(loop [costs (prepare-costs a graph)
|
||||
unvisited (set (keys graph))]
|
||||
(let [current-node (get-next-node costs unvisited)
|
||||
current-cost (first (costs current-node))]
|
||||
(cond (nil? current-node)
|
||||
(all-shortest-paths a costs)
|
||||
|
||||
(= current-node b)
|
||||
[current-cost (unwind-path a b costs)]
|
||||
|
||||
:else
|
||||
(recur (reduce (partial process-neighbour
|
||||
current-node
|
||||
current-cost)
|
||||
costs
|
||||
(filter (comp unvisited first)
|
||||
(neighbours current-node graph costs)))
|
||||
(disj unvisited current-node))))))
|
||||
([a graph] (dijkstra a nil graph)))
|
||||
|
||||
|
||||
;; Implementation details
|
||||
|
||||
|
||||
(defn prepare-costs
|
||||
"For given start node A ang graph prepare map of costs to start with
|
||||
(assign maximum value for all nodes and zero for starting one).
|
||||
Also save info about most advantageous parent.
|
||||
Example output: {2 [2147483647 7], 6 [2147483647 14]}
|
||||
^ ^ ^
|
||||
| | |
|
||||
node | |
|
||||
cost----- |
|
||||
parent---------------"
|
||||
[start graph]
|
||||
(assoc (zipmap (keys graph)
|
||||
(repeat [Integer/MAX_VALUE nil]))
|
||||
start [0 start]))
|
||||
|
||||
|
||||
(defn neighbours
|
||||
"Get given node's neighbours along with their own costs and costs of corresponding edges.
|
||||
Example output is: {1 [7 10] 2 [4 15]}
|
||||
^ ^ ^
|
||||
| | |
|
||||
neighbour node label | |
|
||||
neighbour cost --- |
|
||||
edge cost ------"
|
||||
[node graph costs]
|
||||
(->> (graph node)
|
||||
(map (fn [[neighbour edge-cost]]
|
||||
[neighbour [(first (costs neighbour)) edge-cost]]))
|
||||
(into {})))
|
||||
|
||||
|
||||
(defn process-neighbour
|
||||
[parent
|
||||
parent-cost
|
||||
costs
|
||||
[neighbour [old-cost edge-cost]]]
|
||||
(let [new-cost (+ parent-cost edge-cost)]
|
||||
(if (< new-cost old-cost)
|
||||
(assoc costs
|
||||
neighbour
|
||||
[new-cost parent])
|
||||
costs)))
|
||||
|
||||
|
||||
(defn get-next-node [costs unvisited]
|
||||
(->> costs
|
||||
(filter (comp unvisited first))
|
||||
(sort-by (comp first second))
|
||||
ffirst))
|
||||
|
||||
|
||||
(defn unwind-path
|
||||
"Restore path from A to B based on costs data"
|
||||
[a b costs]
|
||||
(letfn [(f [a b costs]
|
||||
(when-not (= a b)
|
||||
(cons b (f a (second (costs b)) costs))))]
|
||||
(cons a (reverse (f a b costs)))))
|
||||
|
||||
|
||||
(defn all-shortest-paths
|
||||
"Get shortest paths for all nodes, along with their costs"
|
||||
[start costs]
|
||||
(let [paths (->> (keys costs)
|
||||
(remove #{start})
|
||||
(map (fn [n] [n (unwind-path start n costs)])))]
|
||||
(into (hash-map)
|
||||
(map (fn [[n p]]
|
||||
[n [(first (costs n)) p]])
|
||||
paths))))
|
||||
|
||||
|
||||
;; Utils
|
||||
|
||||
|
||||
(require '[clojure.pprint :refer [print-table]])
|
||||
|
||||
|
||||
(defn print-solution [solution]
|
||||
(print-table
|
||||
(map (fn [[node [cost path]]]
|
||||
{'node node 'cost cost 'path path})
|
||||
solution)))
|
||||
|
||||
|
||||
;; Solutions
|
||||
|
||||
|
||||
;; Task 1. Implement a version of Dijkstra's algorithm that outputs a set of edges depicting the shortest path to each reachable node from an origin.
|
||||
|
||||
;; see above
|
||||
|
||||
|
||||
;; Task 2. Run your program with the following directed graph starting at node a.
|
||||
|
||||
;; Edges
|
||||
;; Start End Cost
|
||||
;; a b 7
|
||||
;; a c 9
|
||||
;; a f 14
|
||||
;; b c 10
|
||||
;; b d 15
|
||||
;; c d 11
|
||||
;; c f 2
|
||||
;; d e 6
|
||||
;; e f 9
|
||||
|
||||
(def rosetta-graph
|
||||
'{a {b 7 c 9 f 14}
|
||||
b {c 10 d 15}
|
||||
c {d 11 f 2}
|
||||
d {e 6}
|
||||
e {f 9}
|
||||
f {}})
|
||||
|
||||
(def task-2-solution
|
||||
(dijkstra 'a rosetta-graph))
|
||||
|
||||
(print-solution task-2-solution)
|
||||
|
||||
;; Output:
|
||||
;; | node | cost | path |
|
||||
;; |------+------+-----------|
|
||||
;; | b | 7 | (a b) |
|
||||
;; | c | 9 | (a c) |
|
||||
;; | d | 20 | (a c d) |
|
||||
;; | e | 26 | (a c d e) |
|
||||
;; | f | 11 | (a c f) |
|
||||
|
||||
|
||||
;; Task 3. Write a program which interprets the output from the above and use it to output the shortest path from node a to nodes e and f
|
||||
|
||||
(print-solution (select-keys task-2-solution '[e f]))
|
||||
|
||||
;; Output:
|
||||
;; | node | cost | path |
|
||||
;; |------+------+-----------|
|
||||
;; | e | 26 | (a c d e) |
|
||||
;; | f | 11 | (a c f) |
|
||||
Loading…
Add table
Add a link
Reference in a new issue