From 01fa3ffbe926db027036806a61003a42a2ac4241 Mon Sep 17 00:00:00 2001 From: stoney Date: Mon, 4 Aug 2025 14:42:04 +0400 Subject: [PATCH 1/5] aglorithm(bellmanFord): standard template for bellman-ford algorithm --- src/algorithms/bellmanFord.cpp | 56 ++++++++++++++++++++++++++++++++++ src/algorithms/bellmanFord.h | 33 ++++++++++++++++++++ src/board.cpp | 4 ++- 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/algorithms/bellmanFord.cpp create mode 100644 src/algorithms/bellmanFord.h diff --git a/src/algorithms/bellmanFord.cpp b/src/algorithms/bellmanFord.cpp new file mode 100644 index 0000000..0bec4dd --- /dev/null +++ b/src/algorithms/bellmanFord.cpp @@ -0,0 +1,56 @@ +#include "bellmanFord.h" +const long long MAX_VALUE = 1e18; + +BellmanFord::BellmanFord(const vector>>& adj, int startNode) : + graph(adj), + distances(adj.size(), MAX_VALUE), + finished(false), + start(startNode) +{ + distances[startNode] = 0; + history.push_back({startNode, startNode, 0}); +} + +Step BellmanFord::stepForward() { + if (currentStepIndex + 1 < history.size()) { + return history[++currentStepIndex]; + } + + if (finished) { + return {-1, -1, -1}; + } + + return {-1, -1, -1}; +} + +Step BellmanFord::stepBackward() { + if (currentStepIndex <= 0) { + return {-1, -1, -1}; + } + + return history[--currentStepIndex]; +} + +bool BellmanFord::isFinished() const { + return finished && currentStepIndex + 1 >= history.size(); +} + +int BellmanFord::getCurrentStepIndex() const { + return currentStepIndex; +} + +int BellmanFord::getTotalSteps() const { + return history.size(); +} + +Step BellmanFord::getHistory(int index) const { + return history[index]; +} + +int BellmanFord::getStartNode() const { + return start; +} + +int BellmanFord::getCumulativeDistance(int nodeIndex) const { + return distances[nodeIndex]; +} diff --git a/src/algorithms/bellmanFord.h b/src/algorithms/bellmanFord.h new file mode 100644 index 0000000..0e44517 --- /dev/null +++ b/src/algorithms/bellmanFord.h @@ -0,0 +1,33 @@ +#ifndef BELLMANFORD_H +#define BELLMANFORD_H + +#include "traversalAlgorithm.h" +#include + +using std::vector; +using std::pair; + +class BellmanFord : public TraversalAlgorithm { +private: + const vector>>& graph; + vector distances; + bool finished; + int currentStepIndex = -1; + vector history; + int start; + +public: + BellmanFord(const vector>>& adj, int startNode); + + Step stepForward(); + Step stepBackward(); + + bool isFinished() const; + int getCurrentStepIndex() const; + int getTotalSteps() const; + Step getHistory(int index) const; + int getStartNode() const; + int getCumulativeDistance(int nodeIndex) const; +}; + +#endif diff --git a/src/board.cpp b/src/board.cpp index af44f92..46f745a 100644 --- a/src/board.cpp +++ b/src/board.cpp @@ -157,6 +157,7 @@ void Board::drawNodes() { } DrawCircle(nodePosition.x, nodePosition.y, node.getNodeRadius(), color); + DrawRing(nodePosition, node.getNodeRadius() - node.getNodeRadius() / 8, node.getNodeRadius(), 0.0f, 360.0f, 100, BLACK); } } @@ -170,7 +171,8 @@ void Board::drawEdges() { if (!neighbor->isNodeValid()) continue; Color color = highlightedEdges.count({node.getNodeIndex(), neighbor->getNodeIndex()}) ? DARKBLUE : GREEN; - DrawLineEx(node.getNodePosition(), neighbor->getNodePosition(), 5.0f, color); + DrawLineEx(node.getNodePosition(), neighbor->getNodePosition(), 6.0f, color); + // DrawLineEx(node.getNodePosition(), neighbor->getNodePosition(), 2.0f, color); } } } From a7b4ea8dee204c06f21de0fab1f024b87f343b09 Mon Sep 17 00:00:00 2001 From: stoney Date: Mon, 4 Aug 2025 15:07:44 +0400 Subject: [PATCH 2/5] alg(bellmanFord): bellman ford logic done --- CMakeLists.txt | 1 + src/algorithms/bellmanFord.cpp | 35 +++++++++++++++++++++++++++++++++- src/algorithms/bellmanFord.h | 8 +++++++- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d62a1ac..adcb98d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES src/algorithms/bfs.cpp src/algorithms/dfs.cpp src/algorithms/dijkstra.cpp + src/algorithms/bellmanFord.cpp ) add_executable(${PROJECT_NAME} ${SOURCES}) diff --git a/src/algorithms/bellmanFord.cpp b/src/algorithms/bellmanFord.cpp index 0bec4dd..e14859c 100644 --- a/src/algorithms/bellmanFord.cpp +++ b/src/algorithms/bellmanFord.cpp @@ -7,8 +7,16 @@ BellmanFord::BellmanFord(const vector>>& adj, int startNod finished(false), start(startNode) { + vertices = graph.size(); distances[startNode] = 0; history.push_back({startNode, startNode, 0}); + + // flatten edges + for (int node = 0; node < vertices; node++) { + for (const auto& [neighbor, weight] : graph[node]) { + edges.emplace_back(node, neighbor, weight); + } + } } Step BellmanFord::stepForward() { @@ -16,11 +24,36 @@ Step BellmanFord::stepForward() { return history[++currentStepIndex]; } + if (currentPhase >= vertices - 1) { + finished = true; + return {-1, -1, -1}; + } + if (finished) { return {-1, -1, -1}; + } + + auto [node, neighbor, weight] = edges[currentEdgeIndex]; + bool relaxed = false; + if (distances[node] != MAX_VALUE && distances[node] + weight < distances[neighbor]) { + distances[neighbor] = distances[node] + weight; + relaxed = true; + } + + Step step = Step({node, neighbor, distances[neighbor]}); + history.push_back(step); + currentStepIndex++; + + if (++currentEdgeIndex >= edges.size()) { + currentEdgeIndex = 0; + currentPhase++; + } + + if (currentPhase >= vertices - 1) { + finished = true; } - return {-1, -1, -1}; + return step; } Step BellmanFord::stepBackward() { diff --git a/src/algorithms/bellmanFord.h b/src/algorithms/bellmanFord.h index 0e44517..1063457 100644 --- a/src/algorithms/bellmanFord.h +++ b/src/algorithms/bellmanFord.h @@ -3,6 +3,7 @@ #include "traversalAlgorithm.h" #include +#include using std::vector; using std::pair; @@ -10,11 +11,16 @@ using std::pair; class BellmanFord : public TraversalAlgorithm { private: const vector>>& graph; + vector> edges; vector distances; bool finished; - int currentStepIndex = -1; vector history; + + int currentStepIndex = -1; int start; + int vertices; + int currentPhase; + int currentEdgeIndex; public: BellmanFord(const vector>>& adj, int startNode); From a60fdc60869a9688237fd0e6ddace709f174d203 Mon Sep 17 00:00:00 2001 From: stoney Date: Mon, 4 Aug 2025 15:16:39 +0400 Subject: [PATCH 3/5] alg(bellmanFord): bellman ford button and algorithm operates as intended --- src/board.cpp | 15 +++++++++++++++ src/board.h | 2 ++ src/main.cpp | 7 +++++++ 3 files changed, 24 insertions(+) diff --git a/src/board.cpp b/src/board.cpp index 46f745a..a068175 100644 --- a/src/board.cpp +++ b/src/board.cpp @@ -285,6 +285,21 @@ void Board::runDijkstra(const Vector2& startNodePosition) { } } +void Board::runBellmanFord(const Vector2& startNodePosition) { + if (!isGraphWeighted()) { + std::cout << "Graph must be weighted to run dijkstra\n"; + return; + } + + Node* startNode = findNodeFromPosition(startNodePosition); + if (startNode) { + resetRunning(); + startNodeIndex = -1; + currentAlgo = std::make_unique(graph, startNode->getNodeIndex()); + isRunning = true; + } +} + void Board::highlightNode(const int& index) { if (index >= 0 && index < nodes.size() && nodes[index].isNodeValid()) { nodes[index].setHighlight(); diff --git a/src/board.h b/src/board.h index 28e0d43..d2f20f4 100644 --- a/src/board.h +++ b/src/board.h @@ -9,6 +9,7 @@ #include "algorithms/bfs.h" #include "algorithms/dfs.h" #include "algorithms/dijkstra.h" +#include "algorithms/bellmanFord.h" using std::vector; @@ -54,6 +55,7 @@ class Board { void runBFS(const Vector2& startNodePosition); void runDFS(const Vector2& startNodePosition); void runDijkstra(const Vector2& startNodePosition); + void runBellmanFord(const Vector2& startNodePosition); void stepForward(); void stepBackward(); diff --git a/src/main.cpp b/src/main.cpp index da9f759..ac02a9a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -67,6 +67,12 @@ void handleLeftClick(Board& board, Sidebar& sidebar, Vector2 mouse) { return; } + if (sidebar.isButtonClicked("Bellman-Ford")) { + board.runBellmanFord(startNode); + sidebar.resetClicks(); + return; + } + if (sidebar.isButtonClicked("Weighted")) { if (!board.isGraphEmpty()) { return; // can't flip the graph weight if edges were added. @@ -171,3 +177,4 @@ int main() { CloseWindow(); } + From 0b623fc29a80e3d0ea89131e569a71dd7d2e0b2e Mon Sep 17 00:00:00 2001 From: stoney Date: Mon, 4 Aug 2025 15:39:36 +0400 Subject: [PATCH 4/5] fix(highlight): hiding relaxation steps and highlighting only visually visible steps --- src/algorithms/bellmanFord.cpp | 19 +++++++++++-------- src/algorithms/bellmanFord.h | 2 +- src/algorithms/traversalAlgorithm.h | 10 ++++++++++ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/algorithms/bellmanFord.cpp b/src/algorithms/bellmanFord.cpp index e14859c..8f84271 100644 --- a/src/algorithms/bellmanFord.cpp +++ b/src/algorithms/bellmanFord.cpp @@ -9,7 +9,7 @@ BellmanFord::BellmanFord(const vector>>& adj, int startNod { vertices = graph.size(); distances[startNode] = 0; - history.push_back({startNode, startNode, 0}); + history.push_back({startNode, startNode, 0, true}); // flatten edges for (int node = 0; node < vertices; node++) { @@ -40,10 +40,6 @@ Step BellmanFord::stepForward() { relaxed = true; } - Step step = Step({node, neighbor, distances[neighbor]}); - history.push_back(step); - currentStepIndex++; - if (++currentEdgeIndex >= edges.size()) { currentEdgeIndex = 0; currentPhase++; @@ -53,7 +49,14 @@ Step BellmanFord::stepForward() { finished = true; } - return step; + if (relaxed) { + BellmanStep step = BellmanStep({node, neighbor, distances[neighbor], relaxed}); + history.push_back(step); + currentStepIndex++; + return step.toStep(); + } else { + return stepForward(); + } } Step BellmanFord::stepBackward() { @@ -61,7 +64,7 @@ Step BellmanFord::stepBackward() { return {-1, -1, -1}; } - return history[--currentStepIndex]; + return history[--currentStepIndex].toStep(); } bool BellmanFord::isFinished() const { @@ -77,7 +80,7 @@ int BellmanFord::getTotalSteps() const { } Step BellmanFord::getHistory(int index) const { - return history[index]; + return history[index].toStep(); } int BellmanFord::getStartNode() const { diff --git a/src/algorithms/bellmanFord.h b/src/algorithms/bellmanFord.h index 1063457..b9e83e6 100644 --- a/src/algorithms/bellmanFord.h +++ b/src/algorithms/bellmanFord.h @@ -14,7 +14,7 @@ class BellmanFord : public TraversalAlgorithm { vector> edges; vector distances; bool finished; - vector history; + vector history; int currentStepIndex = -1; int start; diff --git a/src/algorithms/traversalAlgorithm.h b/src/algorithms/traversalAlgorithm.h index a3a62a2..2f65e71 100644 --- a/src/algorithms/traversalAlgorithm.h +++ b/src/algorithms/traversalAlgorithm.h @@ -10,6 +10,16 @@ struct Step { long long distance; }; +struct BellmanStep : Step { + bool relaxed; + BellmanStep(int from, int to, long long distance, bool relaxed) : + Step{from, to, distance}, relaxed(relaxed) {} + + Step toStep() const { + return Step{from, to, distance}; + } +}; + class TraversalAlgorithm { public: From 6beb65a9617256dfd3cc03066869e56e1313fb05 Mon Sep 17 00:00:00 2001 From: stoney Date: Mon, 4 Aug 2025 15:42:05 +0400 Subject: [PATCH 5/5] fix(bellmanstep): changed overcomplicated bellman ford step to normal step --- src/algorithms/bellmanFord.cpp | 10 +++++----- src/algorithms/bellmanFord.h | 2 +- src/algorithms/traversalAlgorithm.h | 10 ---------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/algorithms/bellmanFord.cpp b/src/algorithms/bellmanFord.cpp index 8f84271..9c2439d 100644 --- a/src/algorithms/bellmanFord.cpp +++ b/src/algorithms/bellmanFord.cpp @@ -9,7 +9,7 @@ BellmanFord::BellmanFord(const vector>>& adj, int startNod { vertices = graph.size(); distances[startNode] = 0; - history.push_back({startNode, startNode, 0, true}); + history.push_back({startNode, startNode, 0}); // flatten edges for (int node = 0; node < vertices; node++) { @@ -50,10 +50,10 @@ Step BellmanFord::stepForward() { } if (relaxed) { - BellmanStep step = BellmanStep({node, neighbor, distances[neighbor], relaxed}); + Step step = Step({node, neighbor, distances[neighbor]}); history.push_back(step); currentStepIndex++; - return step.toStep(); + return step; } else { return stepForward(); } @@ -64,7 +64,7 @@ Step BellmanFord::stepBackward() { return {-1, -1, -1}; } - return history[--currentStepIndex].toStep(); + return history[--currentStepIndex]; } bool BellmanFord::isFinished() const { @@ -80,7 +80,7 @@ int BellmanFord::getTotalSteps() const { } Step BellmanFord::getHistory(int index) const { - return history[index].toStep(); + return history[index]; } int BellmanFord::getStartNode() const { diff --git a/src/algorithms/bellmanFord.h b/src/algorithms/bellmanFord.h index b9e83e6..1063457 100644 --- a/src/algorithms/bellmanFord.h +++ b/src/algorithms/bellmanFord.h @@ -14,7 +14,7 @@ class BellmanFord : public TraversalAlgorithm { vector> edges; vector distances; bool finished; - vector history; + vector history; int currentStepIndex = -1; int start; diff --git a/src/algorithms/traversalAlgorithm.h b/src/algorithms/traversalAlgorithm.h index 2f65e71..a3a62a2 100644 --- a/src/algorithms/traversalAlgorithm.h +++ b/src/algorithms/traversalAlgorithm.h @@ -10,16 +10,6 @@ struct Step { long long distance; }; -struct BellmanStep : Step { - bool relaxed; - BellmanStep(int from, int to, long long distance, bool relaxed) : - Step{from, to, distance}, relaxed(relaxed) {} - - Step toStep() const { - return Step{from, to, distance}; - } -}; - class TraversalAlgorithm { public: