Skip to content

Bellman ford #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand Down
92 changes: 92 additions & 0 deletions src/algorithms/bellmanFord.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include "bellmanFord.h"
const long long MAX_VALUE = 1e18;

BellmanFord::BellmanFord(const vector<vector<pair<int, int>>>& adj, int startNode) :
graph(adj),
distances(adj.size(), MAX_VALUE),
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() {
if (currentStepIndex + 1 < history.size()) {
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;
}

if (++currentEdgeIndex >= edges.size()) {
currentEdgeIndex = 0;
currentPhase++;
}

if (currentPhase >= vertices - 1) {
finished = true;
}

if (relaxed) {
Step step = Step({node, neighbor, distances[neighbor]});
history.push_back(step);
currentStepIndex++;
return step;
} else {
return stepForward();
}
}

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];
}
39 changes: 39 additions & 0 deletions src/algorithms/bellmanFord.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef BELLMANFORD_H
#define BELLMANFORD_H

#include "traversalAlgorithm.h"
#include <vector>
#include <tuple>

using std::vector;
using std::pair;

class BellmanFord : public TraversalAlgorithm {
private:
const vector<vector<pair<int, int>>>& graph;
vector<std::tuple<int, int, int>> edges;
vector<long long> distances;
bool finished;
vector<Step> history;

int currentStepIndex = -1;
int start;
int vertices;
int currentPhase;
int currentEdgeIndex;

public:
BellmanFord(const vector<vector<pair<int, int>>>& 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
19 changes: 18 additions & 1 deletion src/board.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -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);
}
}
}
Expand Down Expand Up @@ -283,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<BellmanFord>(graph, startNode->getNodeIndex());
isRunning = true;
}
}

void Board::highlightNode(const int& index) {
if (index >= 0 && index < nodes.size() && nodes[index].isNodeValid()) {
nodes[index].setHighlight();
Expand Down
2 changes: 2 additions & 0 deletions src/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "algorithms/bfs.h"
#include "algorithms/dfs.h"
#include "algorithms/dijkstra.h"
#include "algorithms/bellmanFord.h"
using std::vector;


Expand Down Expand Up @@ -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();
Expand Down
7 changes: 7 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -171,3 +177,4 @@ int main() {

CloseWindow();
}