Skip to content
Draft
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
8 changes: 4 additions & 4 deletions examples/DijkstraExample/dijkstra_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ int main() {
CXXGraph::Node<int> node2("2", 2);
CXXGraph::Node<int> node3("3", 3);

CXXGraph::DirectedWeightedEdge<int> edge1("1", node1, node2, 2.0);
CXXGraph::DirectedWeightedEdge<int> edge2("2", node2, node3, 2.0);
CXXGraph::DirectedWeightedEdge<int> edge3("3", node0, node1, 2.0);
CXXGraph::DirectedWeightedEdge<int> edge4("4", node0, node3, 1.0);
CXXGraph::DirectedWeightedEdge<int> edge1(1, node1, node2, 2.0);
CXXGraph::DirectedWeightedEdge<int> edge2(2, node2, node3, 2.0);
CXXGraph::DirectedWeightedEdge<int> edge3(3, node0, node1, 2.0);
CXXGraph::DirectedWeightedEdge<int> edge4(4, node0, node3, 1.0);

CXXGraph::T_EdgeSet<int> edgeSet;
edgeSet.insert(make_shared<CXXGraph::DirectedWeightedEdge<int>>(edge1));
Expand Down
147 changes: 147 additions & 0 deletions include/CXXGraph/Graph/Algorithm/Dijkstra_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,76 +157,76 @@
}

template <typename T>
const DijkstraResult Graph<T>::dijkstra_deterministic(
const Node<T>& source, const Node<T>& target) const {
DijkstraResult result;
auto nodeSet = Graph<T>::getNodeSet();

auto source_node_it = std::find_if(
nodeSet.begin(), nodeSet.end(),
[&source](auto node) { return node->getUserId() == source.getUserId(); });
if (source_node_it == nodeSet.end()) {
// check if source node exist in the graph
result.errorMessage = ERR_SOURCE_NODE_NOT_IN_GRAPH;
return result;
}

auto target_node_it = std::find_if(
nodeSet.begin(), nodeSet.end(),
[&target](auto node) { return node->getUserId() == target.getUserId(); });
if (target_node_it == nodeSet.end()) {
// check if target node exist in the graph
result.errorMessage = ERR_TARGET_NODE_NOT_IN_GRAPH;
return result;
}
// n denotes the number of vertices in graph
// unused
// auto n = cachedAdjListOut->size();

// setting all the distances initially to INF_DOUBLE
std::unordered_map<shared<const Node<T>>, double, nodeHash<T>> dist;
std::map<std::string, shared<const Node<T>>> userIds;

for (const auto& node : nodeSet) {
dist[node] = INF_DOUBLE;
userIds[node->getUserId()] = node;
}

std::unordered_map<shared<const Node<T>>, size_t, nodeHash<T>> stableIds;
size_t index(0);
for (const auto& it : userIds) stableIds[it.second] = index++;

// creating a min heap using priority queue
// first element of pair contains the distance
// second element of pair contains the vertex

struct VertexInfo {
double distance = 0;
size_t sumOfIds = 0;
shared<const Node<T>> node;
};

struct VertexInfoGreater {
bool operator()(const VertexInfo& a, const VertexInfo& b) const {
if (a.distance == b.distance) return a.sumOfIds > b.sumOfIds;
return a.distance > b.distance;
};
};

std::priority_queue<VertexInfo, std::vector<VertexInfo>, VertexInfoGreater>
pq;

// pushing the source vertex 's' with 0 distance in min heap
pq.push(VertexInfo{0.0, stableIds[*source_node_it], *source_node_it});

// marking the distance of source as 0
dist[*source_node_it] = 0;

std::unordered_map<std::string, std::string> parent;
parent[source.getUserId()] = "";

while (!pq.empty()) {
// second element of pair denotes the node / vertex

Check notice

Code scanning / Cppcheck (reported by Codacy)

The scope of the variable 'currentNodesSum' can be reduced. Note

The scope of the variable 'currentNodesSum' can be reduced.
shared<const Node<T>> currentNode = pq.top().node;
// first element of pair denotes the distance
double currentDist = pq.top().distance;
Expand Down Expand Up @@ -284,7 +284,7 @@
}
}
}
if (dist[*target_node_it] != INF_DOUBLE) {

Check warning

Code scanning / Cppcheck (reported by Codacy)

Because of missing configuration, misra checking is incomplete. There can be false negatives! Variable 'INF_DOUBLE' is unknown Warning

Because of missing configuration, misra checking is incomplete. There can be false negatives! Variable 'INF_DOUBLE' is unknown
result.success = true;
result.errorMessage = "";
result.result = dist[*target_node_it];
Expand Down Expand Up @@ -329,7 +329,7 @@
// auto n = cachedAdjListOut->size();

// setting all the distances initially to INF_DOUBLE
std::unordered_map<shared<const Node<T>>, double, nodeHash<T>> dist;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
std::map<std::string, shared<const Node<T>>> userIds;

for (const auto& node : nodeSet) {
Expand Down Expand Up @@ -375,14 +375,14 @@
// marking the distance of source as 0
dist[*source_node_it] = 0;

std::unordered_map<std::string, std::string> parent;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
parent[source.getUserId()] = "";

while (!pq.empty()) {
// second element of pair denotes the node / vertex
shared<const Node<T>> currentNode = pq.top().node;
// first element of pair denotes the distance
double currentDist = pq.top().distance;

Check notice

Code scanning / Cppcheck (reported by Codacy)

The scope of the variable 'currentDist' can be reduced. Note

The scope of the variable 'currentDist' can be reduced.
auto currentNodesPath = pq.top().pathToVertex;

pq.pop();
Expand Down Expand Up @@ -483,7 +483,7 @@

// setting all the distances initially to -INF_DOUBLE
std::unordered_map<shared<const Node<T>>, double, nodeHash<T>> dist;
std::map<std::string, shared<const Node<T>>> userIds;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule

for (const auto& node : nodeSet) {
dist[node] = -INF_DOUBLE;
Expand Down Expand Up @@ -598,5 +598,152 @@
return result;
}

template <typename T>
const DijkstraResult Graph<T>::criticalpath_deterministic(
const Node<T>& source, const Node<T>& target) const {
DijkstraResult result;
auto nodeSet = Graph<T>::getNodeSet();

auto source_node_it = std::find_if(
nodeSet.begin(), nodeSet.end(),
[&source](auto node) { return node->getUserId() == source.getUserId(); });
if (source_node_it == nodeSet.end()) {
// check if source node exist in the graph
result.errorMessage = ERR_SOURCE_NODE_NOT_IN_GRAPH;
return result;
}

auto target_node_it = std::find_if(
nodeSet.begin(), nodeSet.end(),
[&target](auto node) { return node->getUserId() == target.getUserId(); });
if (target_node_it == nodeSet.end()) {
// check if target node exist in the graph
result.errorMessage = ERR_TARGET_NODE_NOT_IN_GRAPH;
return result;
}
// n denotes the number of vertices in graph
// unused
// auto n = cachedAdjMatrix->size();

// setting all the distances initially to -INF_DOUBLE
std::unordered_map<shared<const Node<T>>, double, nodeHash<T>> dist;
std::map<std::string, shared<const Node<T>>> userIds;

for (const auto& node : nodeSet) {
dist[node] = -INF_DOUBLE;
userIds[node->getUserId()] = node;
}

std::unordered_map<shared<const Node<T>>, size_t, nodeHash<T>> stableIds;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
size_t index(0);
for (const auto& it : userIds) stableIds[it.second] = index++;

// creating a max heap using priority queue
// first element of pair contains the distance
// second element of pair contains the vertex

struct VertexInfo {
double distance = 0;
size_t sumOfIds = 0;
shared<const Node<T>> node;
};

struct VertexInfoLesser {
bool operator()(const VertexInfo& a, const VertexInfo& b) const {
if (a.distance == b.distance) return a.sumOfIds < b.sumOfIds;
return a.distance < b.distance;
};
};

std::priority_queue<VertexInfo, std::vector<VertexInfo>, VertexInfoLesser> pq;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule

// pushing the source vertex 's' with 0 distance in min heap
pq.push(VertexInfo{0.0, stableIds[*source_node_it], *source_node_it});

// marking the distance of source as 0
dist[*source_node_it] = 0;

std::unordered_map<std::string, std::string> parent;
parent[source.getUserId()] = "";

while (!pq.empty()) {
// second element of pair denotes the node / vertex
shared<const Node<T>> currentNode = pq.top().node;
// first element of pair denotes the distance
double currentDist = pq.top().distance;
auto currentNodesSum = pq.top().sumOfIds;

pq.pop();

// for all the reachable vertex from the currently exploring vertex
// we will try to minimize the distance
if (cachedAdjMatrix->find(currentNode) != cachedAdjMatrix->end()) {
for (const auto& elem : cachedAdjMatrix->at(currentNode)) {

Check warning

Code scanning / Cppcheck (reported by Codacy)

Because of missing configuration, misra checking is incomplete. There can be false negatives! Variable 'cachedAdjMatrix' is unknown Warning

Because of missing configuration, misra checking is incomplete. There can be false negatives! Variable 'cachedAdjMatrix' is unknown
// minimizing distances
if (elem.second->isWeighted().has_value() &&
elem.second->isWeighted().value()) {
if (elem.second->isDirected().has_value() &&
elem.second->isDirected().value()) {
shared<const DirectedWeightedEdge<T>> dw_edge =
std::static_pointer_cast<const DirectedWeightedEdge<T>>(
elem.second);
if (dw_edge->getWeight() < 0) {
result.errorMessage = ERR_NEGATIVE_WEIGHTED_EDGE;
return result;
} else if (currentDist + dw_edge->getWeight() > dist[elem.first]) {
dist[elem.first] = currentDist + dw_edge->getWeight();
pq.push(VertexInfo{dist[elem.first],
currentNodesSum + stableIds[elem.first],
elem.first});
parent[elem.first.get()->getUserId()] =
currentNode.get()->getUserId();
}
} else if (elem.second->isDirected().has_value() &&
!elem.second->isDirected().value()) {
shared<const UndirectedWeightedEdge<T>> udw_edge =
std::static_pointer_cast<const UndirectedWeightedEdge<T>>(
elem.second);
if (udw_edge->getWeight() < 0) {
result.errorMessage = ERR_NEGATIVE_WEIGHTED_EDGE;
return result;
} else if (currentDist + udw_edge->getWeight() > dist[elem.first]) {
dist[elem.first] = currentDist + udw_edge->getWeight();
pq.push(VertexInfo{dist[elem.first],
currentNodesSum + stableIds[elem.first],
elem.first});
parent[elem.first.get()->getUserId()] =
currentNode.get()->getUserId();
}
} else {
// ERROR it shouldn't never returned ( does not exist a Node
// Weighted and not Directed/Undirected)
result.errorMessage = ERR_NO_DIR_OR_UNDIR_EDGE;
return result;
}
} else {
// No Weighted Edge
result.errorMessage = ERR_NO_WEIGHTED_EDGE;
return result;
}
}
}
}
if (dist[*target_node_it] != INF_DOUBLE) {
result.success = true;
result.errorMessage = "";
result.result = dist[*target_node_it];
std::string id = target.getUserId();
while (parent[id] != "") {
result.path.push_back(id);
id = parent[id];
}
result.path.push_back(source.getUserId());
std::reverse(result.path.begin(), result.path.end());
return result;
}
result.errorMessage = ERR_TARGET_NODE_NOT_REACHABLE;
return result;
}

} // namespace CXXGraph
#endif // __CXXGRAPH_DIJKSTRA_IMPL_H__
Loading