'Dijkstra's full algorithm using BFS and dictionary bug
Using dictionaries, graphs, and lists, I'm attempting to implement the Dijkstra algorithm with BFS in Clojure. The issue is that I can't get it to work correctly; it won't work when I ask it to return the solution with weights, and it also won't work when I ask it to produce the graph without weights. The problem occurs, most likely, at the BFS function; I would very appreciate any assistance with this. I tried to search for information online and spoke with some of my classmates, but unfortunately it didn't help at all.
The files: e-roads-2020-full.clj + project.clj are in GitHub https://github.com/wfgemyd/clojure
;; state 0 - not encountered at all
;; state 1 - in the open queue
;; state 2 - current vertex
;; state 3 - visited
(defn al-papi [queue graph] ;;looks for the best vertex and dist
(loop [queue queue
best-distance nil
best-vertex nil]
(if (empty? queue)
best-vertex
(let [queue-label (first queue)
queue-vertex (get @(:vertices graph) queue-label)]
(if (or (nil? best-vertex) (< @(:distance queue-vertex) best-distance))
(recur (rest queue) @(:distance queue-vertex) queue-vertex)
(recur (rest queue) best-distance best-vertex))))))
(defn graph-bfs!
([graph]
(graph-bfs! graph (first (keys @(:vertices graph)))))
([graph start]
(graph-bfs! graph start (fn [vertex] nil)))
([graph start func]
(graph-bfs! graph start func first))
([graph start func func-m]
(let [vertices @(:vertices graph)]
(loop [queue (list start)]
(when (not (empty? queue))
(let [current-label (if (= func-m al-papi)(func-m queue graph)(func-m queue))
rest-queue (rest-queue! queue current-label)
current-vertex (get vertices current-label)
visited-status (:visited current-vertex)
current-neighbors @(:neighbors current-vertex)
unseen-neighbors (filter
(fn [label]
(= @(:visited (get vertices label)) 0))
current-neighbors)
]
(dosync (ref-set visited-status 2))
(func current-vertex)
(dosync (ref-set visited-status 3))
(doseq [label unseen-neighbors]
(dosync
(ref-set (:visited (get vertices label)) 1)))
(recur (concat rest-queue unseen-neighbors))))))))
(defn graph-dijkstra-mark! [graph finish use-weights]
(let [vertices @(:vertices graph)
start-vertex (get vertices finish)]
(graph-reset! graph)
(dosync
(ref-set (:distance start-vertex) 0))
(if (not use-weights)
(graph-bfs! graph
finish
(fn [vertex]
(let [next-distance (inc @(:distance vertex))]
(doseq [neighbor-label @(:neighbors vertex)]
(let [neighbor (get vertices neighbor-label)]
(if (= @(:visited neighbor) 0)
(dosync
(ref-set (:distance neighbor) next-distance))))))))
(graph-bfs! graph
finish
(fn [vertex]
(doseq [neighbor-label @(:neighbors vertex)]
(let [neighbor (get vertices neighbor-label)
next-distance (+ @(:distance vertex) (get-edge-weight graph (:label vertex) neighbor-label))]
(println "There is bfs!")
(when (or (= @(:visited neighbor) 0) (> @(:distance neighbor) next-distance))
(dosync
(ref-set (:distance neighbor) next-distance))))))
al-papi))))
Solution 1:[1]
Found the bug, it was in the back trace function, it was returning the ref and not the actual data that was needed in the function, plus the function "al-papi" was returning the best-vertex and not the :label of the best-vertex.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Daniel Shutov |