I'm trying to store the path Dijkstra's does when it calculates shortest path to every vertice from the source. This is currently what I'm doing right now but I'm struggling with how to actually store the path. I was hoping if someone can help me. You should also note that currently the u value's are ints and I want to return this specific path as characters. The array size is 26 by 26 as there are 26 characters in the alphabet. A possible path could be C B A, or 2, 1, 0.
void dijkstra(int graph[MAX_ROWS][MAX_COLUMNS], int src){
int dist[MAX_ROWS]; // The output array. dist[i] will hold the shortest distance from src to i
bool sptSet[MAX_ROWS]; // sptSet[i] will true if vertex i is included in shortest path tree or shortest distance from src to i is finalized
int i, count, v;
struct path {
char thepath[40];
} pathArray[MAX_ROWS];
// Initialize all distances as INFINITE and stpSet[] as false
for (i = 0; i < MAX_ROWS; i++)
dist[i] = INT_MAX, sptSet[i] = false;
// Distance of source vertex from itself is always 0
dist[src] = 0;
// Find shortest path for all vertices
for (count = 0; count < MAX_ROWS-1; count++){
// Pick the minimum distance vertex from the set of vertices not
// yet processed. u is always equal to src in first iteration.
int u = minDistance(dist, sptSet);
int baby = u + 'A';
char girl = baby;
printf("Count : %d, u : %c\n", count, girl);
pathArray[v].thepath[v] = girl;
// Mark the picked vertex as processed
sptSet[u] = true;
// Update dist value of the adjacent vertices of the picked vertex.
for (v = 0; v < MAX_ROWS; v++)
// Update dist[v] only if is not in sptSet, there is an edge from
// u to v, and total weight of path from src to v through u is
// smaller than current value of dist[v]
if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX && dist[u]+graph[u][v] < dist[v]){
dist[v] = dist[u] + graph[u][v];
}
}
// print the constructed distance array
printf("Vertex Distance from Source\n");
for (i = 0; i < MAX_ROWS; i++){
if (dist[i] != INT_MAX)
printf("%d \t\t %d Path: %s\n", i, dist[i], pathArray[i].thepath);
}
//printSolution(dist, MAX_ROWS, pathArray.thepath);
}
Your approach of pathArray has some problems:
First, you address the path via the vertex v, but v is uninitialised and it does not have any meaning outside the for loop.
Also, v isn't any meaningful information for the string: It is a vertex id. You also have the distance to the source, but the string index you need requires the number of steps to reach v from the source vertex, which you currently don't store.
Finally, you can only build your paths when all distances have been found, not during pathfinding.
A better approach is to keep an array prev[MAX_ROWS] that stores the vertex id of the vertex that lies directly before this vertex in the shortest path from the source to this vertex. That means you essentially store the path from the destination to the source. You can't do it the other way round, because the paths from the source may fork. Seen from the other end, that means that all paths eventually join when going towards the source, so storing the path as list of previous points is safe.
You set the previous vertex whenever you find a new shortest distance:
if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX
&& dist[u]+graph[u][v] < dist[v])
{
dist[v] = dist[u] + graph[u][v];
prev[v] = u;
}
You can then print the path from each vertex i to the source:
v = i;
while (v != src) {
putchar('A' + v);
v = prev[v];
}
putchar('A' + src);
putchar(10);
If you want to store the forward-going path, you can implement a recursive approach or write the path to a string and then reverse it.
Related
I am trying to parallelize Dijkstra using OpenMP, but the program is not working correctly. Sometimes the correct results are displayed while other times I get wrong values, I assume this is because multiple threads are updating the same variable. However I cannot find the source of this problem because I am making shared variable updates inside critical regions. Can someone please help me identify what mistake am I making my assignment is due soon and is this code conceptually correct?
int minDistance(int s,int e,int dist[], bool sptSet[])
{
// Initialize min value
int mini = INT_MAX, min_index;
for (int v = s; v <= e; v++){
if (sptSet[v] == false && dist[v] < mini){
mini = dist[v];
min_index = v;
}
//printf("min_ind %d\n",min_index);
}
return min_index;
}
void Update(int graph[V][V],int s,int e,int hold,int dist[], bool sptSet[]){
for (int v = s; v <= e; v++){
// Update dist[v] only if is not in sptSet,
// there is an edge from u to v, and total
// weight of path from src to v through u is
// smaller than current value of dist[v]
if (!sptSet[v] && graph[hold][v] && dist[hold] != INT_MAX && dist[hold] + graph[hold][v] < dist[v]){
dist[v] = dist[hold] + graph[hold][v];
}
}
}
void dijkstra(int graph[V][V],int src)
{
int dist[V]; // The output array. dist[i] will hold the
// shortest
// distance from src to i
bool sptSet[V]; // sptSet[i] will be true if vertex i is
// included in shortest
// path tree or shortest distance from src to i is
// finalized
// Initialize all distances as INFINITE and stpSet[] as
// false
for (int i = 0; i < V; i++)
dist[i] = INT_MAX, sptSet[i] = false;
// Distance of source vertex from itself is always 0
dist[src] = 0;
int min;
int hold;
int u;
// Find shortest path for all vertices
float start = omp_get_wtime();
#pragma omp parallel shared(hold) private(u) num_threads(3)
{
min=INT_MAX;
int x = omp_get_num_threads();
int chunk = V/x;
int me = omp_get_thread_num();
int startv = me * chunk;
int endv = startv + chunk - 1;
int count = 0;
for (count = 0; count < V - 1; count++) {
// Pick the minimum distance vertex from the set of
// vertices not yet processed. u is always equal to
// src in the first iteration.
u = minDistance(startv,endv,dist, sptSet);
//updating overall minimum
#pragma omp critical
{
if(min > dist[u]){
min = dist[u];
hold = u;
}
}
//waiting for all threads to execute critical section bfr proceeding
#pragma omp barrier
// Mark the picked vertex as processed
#pragma omp single
{
sptSet[hold] = true;
}
#pragma omp barrier
// Update dist value of the adjacent vertices of the
// picked vertex.
Update(graph,startv,endv,hold,dist,sptSet);
min = INT_MAX;
}
}
float end = omp_get_wtime();
// print the constructed distance array
printSolution(dist);
printf("Running time: %f ms\n", (end - start)*1000);
}
----------------THE SERIAL CODE:--------------------
int minDistance(int dist[], bool sptSet[])
{
// Initialize min value
int min = INT_MAX, min_index;
for (int v = 0; v < V; v++)
if (sptSet[v] == false && dist[v] <= min)
min = dist[v], min_index = v;
return min_index;
}
// A utility function to print the constructed distance
// array
void printSolution(int dist[])
{
printf("Vertex \t\t Distance from Source\n");
for (int i = 0; i < V; i++)
printf("%d \t\t\t\t %d\n", i, dist[i]);
}
// Function that implements Dijkstra's single source
// shortest path algorithm for a graph represented using
// adjacency matrix representation
void dijkstra(int graph[V][V], int src)
{
int dist[V]; // The output array. dist[i] will hold the
// shortest
// distance from src to i
bool sptSet[V]; // sptSet[i] will be true if vertex i is
// included in shortest
// path tree or shortest distance from src to i is
// finalized
// Initialize all distances as INFINITE and stpSet[] as
// false
for (int i = 0; i < V; i++)
dist[i] = INT_MAX, sptSet[i] = false;
// Distance of source vertex from itself is always 0
dist[src] = 0;
// Find shortest path for all vertices
for (int count = 0; count < V - 1; count++) {
// Pick the minimum distance vertex from the set of
// vertices not yet processed. u is always equal to
// src in the first iteration.
int u = minDistance(dist, sptSet);
// Mark the picked vertex as processed
sptSet[u] = true;
// Update dist value of the adjacent vertices of the
// picked vertex.
for (int v = 0; v < V; v++)
{
// Update dist[v] only if is not in sptSet,
// there is an edge from u to v, and total
// weight of path from src to v through u is
// smaller than current value of dist[v]
if (!sptSet[v] && graph[u][v]
&& dist[u] != INT_MAX
&& dist[u] + graph[u][v] < dist[v])
dist[v] = dist[u] + graph[u][v];
}
}
// print the constructed distance array
printSolution(dist);
}
Dijkstra's algorithm is a good example of an algorithm where the standard formulation is very hard to parallelize. Every step of 1. finding the minimum 2. updating its neighbors depends on the previous. Therefore the best you can do is 1. making that minimum into an OpenMP reduction 2. making the update into a parallel loop. On graphs with small degree this will not give you much speedup. It also means taht your code is not correct: you are trying to parallelize over the outer steps, which are sequential.
However, you don't have to update only the neighbors of that minimum point: you can update all points in every step. That simplifies the code, and reduces overhead. It also does more work, but in wall clock time it may finish slightly faster.
I have implemented my graph in adjacency list. How can I estimate one vertex reachability from another when user provides indexes?
int isReachable(int nodes, int graph[nodes][nodes], int src, int dest)
Checking for direct neighbors is easy, but I struggle with implementing algorithm as whole.
Code from: http://www.geeksforgeeks.org/transitive-closure-of-a-graph/
int reach[V][V], i, j, k;
/* Initialize the solution matrix same as input graph matrix. Or
we can say the initial values of shortest distances are based
on shortest paths considering no intermediate vertex. */
for (i = 0; i < V; i++)
for (j = 0; j < V; j++)
reach[i][j] = graph[i][j];
/* Add all vertices one by one to the set of intermediate vertices.
---> Before start of a iteration, we have reachability values for
all pairs of vertices such that the reachability values
consider only the vertices in set {0, 1, 2, .. k-1} as
intermediate vertices.
----> After the end of a iteration, vertex no. k is added to the
set of intermediate vertices and the set becomes {0, 1, .. k} */
for (k = 0; k < V; k++)
{
// Pick all vertices as source one by one
for (i = 0; i < V; i++)
{
// Pick all vertices as destination for the
// above picked source
for (j = 0; j < V; j++)
{
// If vertex k is on a path from i to j,
// then make sure that the value of reach[i][j] is 1
reach[i][j] = reach[i][j] || (reach[i][k] && reach[k][j]);
}
}
}
// Print the shortest distance matrix
printSolution(reach);
}
Given a roadmap between a number of cities, with roads between 2 cities containing tunnels, your goal is to find the shortest possible paths between the start city and all the other cities, such that each path contains at least one tunnel. (The problem doesn't always have a solution). Assume the cost of the roads is given. Input - from a file, output - to a file, containing the start city and the path to the rest of the cities.
Now I tried to do this with Dijkstra's algorithm, it solved most of my problem except the part where tunnels are mandatory. Can anyone help me with this? This is my code.
Thanks in advance!
File input:
10
1 2 10
1 4 5
2 3 1
2 4 3
3 5 6
4 2 2
4 3 9
4 5 2
5 1 7
5 3 4
#include <stdio.h>
#define GRAPHSIZE 2048
#define INFINITY GRAPHSIZE*GRAPHSIZE
#define MAX(a, b) ((a > b) ? (a) : (b))
int e; /* The number of nonzero edges in the graph */
int n; /* The number of nodes in the graph */
long dist[GRAPHSIZE][GRAPHSIZE];/* dist[i][j] is the distance between node i and j; or 0 if there is no direct connection */
long d[GRAPHSIZE]; /* d[i] is the length of the shortest path between the source (s) and node i */
int prev[GRAPHSIZE]; /* prev[i] is the node that comes right before i in the shortest path from the source to i*/
void printD() {
int i;
printf("Distances:\n");
for (i = 1; i <= n; ++i)
printf("%10d", i);
printf("\n");
for (i = 1; i <= n; ++i) {
printf("%10ld", d[i]);
}
printf("\n");
}
/*
* Prints the shortest path from the source to dest.
* dijkstra(int) MUST be run at least once BEFORE
* this is called
*/
void printPath(int dest) {
if (prev[dest] != -1)
printPath(prev[dest]);
printf("%d ", dest);
}
void dijkstra(int s) {
int i, k, mini;
int visited[GRAPHSIZE];
for (i = 1; i <= n; ++i) {
d[i] = INFINITY;
prev[i] = -1; /* no path has yet been found to i */
visited[i] = 0; /* the i-th element has not yet been visited */
}
d[s] = 0;
for (k = 1; k <= n; ++k) {
mini = -1;
for (i = 1; i <= n; ++i)
if (!visited[i] && ((mini == -1) || (d[i] < d[mini])))
mini = i;
visited[mini] = 1;
for (i = 1; i <= n; ++i)
if (dist[mini][i])
if (d[mini] + dist[mini][i] < d[i]) {
d[i] = d[mini] + dist[mini][i];
prev[i] = mini;
}
}
}
int main(int argc, char *argv[]) {
int i, j;
int u, v, w;
FILE *fin = fopen("dist.txt", "r");
/* the first line contains e, the number of edges the following e lines
contain 3 numbers: u, v and w signifying that there’s an edge from u to v of weight w*/
fscanf(fin, "%d", &e);
for (i = 0; i < e; ++i)
for (j = 0; j < e; ++j)
dist[i][j] = 0;
n = -1;
for (i = 0; i < e; ++i) {
fscanf(fin, "%d%d%d", &u, &v, &w);
dist[u][v] = w;
n = MAX(u, MAX(v, n));
}
fclose(fin);
dijkstra(1);
printD();
printf("\n");
for (i = 1; i <= n; ++i) {
printf("Path to %d: ", i);
printPath(i);
printf("\n");
}
return 0;
}
Run Dijkstra's algorithm to find all the shortest paths from the starting city to all tunnels.
The run Dijkstra's algorithm again with all the tunnels as starting points to find all the shortest paths to all the other cities. So you'll sort of start in the middle of Dijkstra's algorithm, where you already have a bunch of candidates (all the tunnels) in your priority queue, and all of these will be marked as visited.
It doesn't look like you're using a priority queue (the efficient implementation of Dijkstra's algorithm uses one), but I'm sure you'll manage to figure out how to apply my solution to your code nonetheless.
You can construct a graph like this: have two nodes per city (say C and C' for each city C). For each road, say from C1 to C2, add edges to the graph: C1->C2 and C1'->C2'. For each tunnel, say from C1 to C2, add edges to the graph C1->C2' and C1'->C2'.
The intuition is that to get to a C' node you have to go through at least one tunnel.
Now, to find the shortest path from C1 to C2 using at least one tunnel, simply use Dijkstra to find the shortest path from C1 to C2'. Or to find shortest paths to each city, find all shortest paths from the start city to C' for each city C.
I'm in the process of creating a maze simulation of a mouse running through a maze. Dijkstra's algorithm is great and all but isn't particularly effected when cats are involved, which is why I'm trying to modify my existing Dijkstra implementation to an A* search with a heuristic for avoiding the cats which move throughout the maze.
The problem I'm having while I look through some pseudocode is I am unsure of what structures are equivalent or what will I need to introduce to get this working. Can anyone provide any tips or nudges in the right direction?
struct path_node *shortestPath(float A[GsizeSqr][GsizeSqr], int xi, int yi, int xf, int yf)
{
/*
Solves for the shortest path between grid point (xi,yi) and (xf,yf)
on the graph encoded by A using Dijkstra's shortest path method.
The shortest path is returned as a linked list of nodes to be visited.
Keep track of visited nodes, and the predecessor
for each node that has been explored while computing the shortest path.*/
if (xi<0||xi>=Gsize&&yi<0&&yi>=Gsize||xf<0||xf>=Gsize||yf<0||yf>=Gsize)
{
fprintf(stderr,"shortestPath(): Endpoint(s) outside of the graph!\n");
return(NULL);
}
int i, j, pCount, findN, row, col, icnt, stNode, finNode, xcnt, ycnt;
finNode = yf * ceil(sqrt(GsizeSqr)) + xf; //index of start node given its row and col value
stNode = yi * ceil(sqrt(GsizeSqr)) + xi; //index of finish node given its row and col value
int p[GsizeSqr]; //predecessors
int d[GsizeSqr]; //distance from source
int flags[GsizeSqr]; //(0, 1) for unvisited, visited)
int g_score[GsizeSqr];
int f_score[GsizeSqr];
PriorityQueue Q; //Initialize priority queue that stores (priority, key) values
Q = init_heap(GsizeSqr);
path_node *start; //Maintain a pointer to the starting node
start = newPathNode(xi, yi);
start->next = NULL;
//Initialize p and d with infinity and NULL values (note: -1 means null and 1000000 means inf)
for(i=0; i < GsizeSqr; i++){
p[i] = -1;
d[i] = 10000000;
flags[i] = 0;
}
for(i=0; i < GsizeSqr; i++){
node in;
in = create_node(10000000, i);
enqueue(Q, in);
}
//(Note: PQ uses 0 as a sentinel node to make calculating left, right, and parents easier, elements begin at 1)
decrease_priority(Q, stNode+1, 0); //setting start node in PQ.
d[stNode] = 0;
g_score[stNode] = 0;
//For my heuristic, I'm thinking just using manhattan distances between mouse and cat agents
f_score[stNode] = g_score[stNode] + heuristic(xi, yi, xf, yf);
while(Q->heap_size != 1){ //while Q not empty
node u;
u = dequeue(Q);
flags[u.key] = 1;
//For each adjacent node A[u.key][i]
for(i=0; i < GsizeSqr; i++){
if(A[u.key][i] != 0){
findN = find_node(Q, i);
if(flags[i] == 0){ //If it is unvisited and new path distance is shorter
if(findN != 0 && (d[i] >= A[u.key][i] + d[u.key])){ //reset values and update PQ and mark visited
d[i] = A[u.key][i] + d[u.key];
p[i] = u.key;
flags[i] = 1;
decrease_priority(Q, findN, d[i]);
}
}
}
}
}
// Begin selectively filling our LL with values from p[]
icnt = finNode;
appendLL(start, xf, yf);
while(icnt != stNode){
icnt = p[icnt];
xcnt = icnt % (int)ceil(sqrt(GsizeSqr));
ycnt = icnt / (int)ceil(sqrt(GsizeSqr));
appendLL(start, xcnt, ycnt);
}
clean_heap(Q);
return reverseLL(start);
}
You possibly already know this, but the only theoretical difference between A* and Dijkstra's algorithm in terms of best-first search is the cost function f(n). Dijkstra's algorithm is f(n) = g(n) whilst A* is f(n) = g(n) + h(n). Read AIMA for details.
In terms of your code, it currently stores g(n) = A[u.key][i] + d[u.key] in d[i], so you need to change it store g(n) + h(n). You don't need those new g_score and f_score variables, just add the heuristic to the end of that line and the initialization of d[stNode].
Hello I have implemented in C Dijkstra's algorithm to find the shortest path, but I need to return the n shortest paths, anyone have an idea how can I do.
My dijkstra function:
int * Dijkstra(graph **g, int totalVertex, int vStart) {
int i;
int *distance = (int*) malloc(totalVertex * sizeof (int));
int *last = (int*) malloc(totalVertex * sizeof (int));
int *visited = (int*) calloc(totalVertex, sizeof (int));
int maxDistance, m;
graph *vertex;
for (i = 0; i < totalVertex; i++) {
distance[i] = MAXINT;
last[i] = -1;
}
distance[vOrigem] = 0;
while (sum(visited, totalVertex) < totalVertex) {
maxDistance = MAXINT;
for (i = 0; i < totalVertex; i++) {
if ((distance[i] < maxDistance) && (visited[i] == 0)) {
maxDistance = distance[i];
m = i;
}
}
vertex = g[m];
while (vertex != NULL) {
if ((vertex->distance + distance[m]) < (distance[vertex-> destination])) {
distance[vertex->destination] = vertex->distance + distance[m];
last[vertex->destination] = m;
}
vertex = vertice->next;
}
visited[m] = 1;
}
free(distance);
free(visited);
return last;
}
I need to call eg 2 times this function and it returns, the two shortest paths in the graph.
Thank you.
Lets start by calling the actual shortest path S and n is the total number of links in S.
This is going to be tough because you could have a ton of permutations of the paths depending on the network configuration and in order to create the next shortest path, you will have to run the algorithm n more times, setting each of the vertices in the shortest path to Visited[m] = 1 for each run in case the next shortest path uses most, but not all of the same vertices from S.
If you really want to only run this for the two shortest paths, then this will be straightforward. If you want to be able to run this to get an arbitrary number of shortest paths, you are exponentially increase your computation time as you go back and set each of the original path links to Visited.