Unable to implement Dijkstra's Algorithm using OpenMP in C - c

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.

Related

Find k out of n subset with maximal area

I have n points and have to find the maximum united area between k points (k <= n). So, its the sum of those points area minus the common area between them.
]1
Suppose we have n=4, k=2. As illustrated in the image above, the areas are calculated from each point to the origin and, the final area is the sum of the B area with the D are (only counting the area of their intersection once). No point is dominated
I have implemented a bottom-up dynamic programming algorithm, but it has an error somewhere. Here is the code, that prints out the best result:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct point {
double x, y;
} point;
struct point *point_ptr;
int n, k;
point points_array[1201];
point result_points[1201];
void qsort(void *base, size_t nitems, size_t size,
int (*compar)(const void *, const void *));
int cmpfunc(const void *a, const void *b) {
point *order_a = (point *)a;
point *order_b = (point *)b;
if (order_a->x > order_b->x) {
return 1;
}
return -1;
}
double max(double a, double b) {
if (a > b) {
return a;
}
return b;
}
double getSingleArea(point p) {
return p.x * p.y;
}
double getCommonAreaX(point biggest_x, point new_point) {
double new_x;
new_x = new_point.x - biggest_x.x;
return new_x * new_point.y;
}
double algo() {
double T[k][n], value;
int i, j, d;
for (i = 0; i < n; i++) {
T[0][i] = getSingleArea(points_array[i]);
}
for (j = 0; j < k; j++) {
T[j][0] = getSingleArea(points_array[0]);
}
for (i = 1; i < k; i++) {
for (j = 1; j < n; j++) {
for (d = 0; d < j; d++) {
value = getCommonAreaX(points_array[j - 1], points_array[j]);
T[i][j] = max(T[i - 1][j], value + T[i - 1][d]);
}
}
}
return T[k - 1][n - 1];
}
void read_input() {
int i;
fscanf(stdin, "%d %d\n", &n, &k);
for (i = 0; i < n; i++) {
fscanf(stdin, "%lf %lf\n", &points_array[i].x, &points_array[i].y);
}
}
int main() {
read_input();
qsort(points_array, n, sizeof(point), cmpfunc);
printf("%.12lf\n", algo());
return 0;
}
with the input:
5 3
0.376508963445 0.437693410334
0.948798695015 0.352125307881
0.176318878234 0.493630156084
0.029394902328 0.951299438575
0.235041868262 0.438197791997
where the first number equals n, the second k and the following lines the x and y coordinates of every point respectively, the result should be: 0.381410589193,
whereas mine is 0.366431740966. So I am missing a point?
This is a neat little problem, thanks for posting! In the remainder, I'm going to assume no point is dominated, that is, there are no points c such that there exists a point d with c.x < d.x and c.y < d.y. If there are, then it is never optimal to use c (why?), so we can safely ignore any dominated points. None of your example points are dominated.
Your problem exhibits optimal substructure: once we have decided which item is to be included in the first iteration, we have the same problem again with k - 1, and n - 1 (we remove the selected item from the set of allowed points). Of course the pay-off depends on the set we choose - we do not want to count areas twice.
I propose we pre-sort all point by their x-value, in increasing order. This ensures the value of a selection of points can be computed as piece-wise areas. I'll illustrate with an example: suppose we have three points, (x1, y1), ..., (x3, y3) with values (2, 3), (3, 1), (4, .5). Then the total area covered by these points is (4 - 3) * .5 + (3 - 2) * 1 + (2 - 0) * 3. I hope it makes sense in a graph:
By our assumption that there are no dominated points, we will always have such a weakly decreasing figure. Thus, pre-sorting solves the entire problem of "counting areas twice"!
Let us turn this into a dynamic programming algorithm. Consider a set of n points, labelled {p_1, p_2, ..., p_n}. Let d[k][m] be the maximum area of a subset of size k + 1 where the (k + 1)-th point in the subset is point p_m. Clearly, m cannot be chosen as the (k + 1)-th point if m < k + 1, since then we would have a subset of size less than k + 1, which is never optimal. We have the following recursion,
d[k][m] = max {d[k - 1][l] + (p_m.x - p_l.x) * p_m.y, for all k <= l < m}.
The initial cases where k = 1 are the rectangular areas of each point. The initial cases together with the updating equation suffice to solve the problem. I estimate the following code as O(n^2 * k). The term squared in n can probably be lowered as well, as we have an ordered collection and might be able to apply a binary search to find the best subset in log n time, reducing n^2 to n log n. I leave this to you.
In the code, I have re-used my notation above where possible. It is a bit terse, but hopefully clear with the explanation given.
#include <stdio.h>
typedef struct point
{
double x;
double y;
} point_t;
double maxAreaSubset(point_t const *points, size_t numPoints, size_t subsetSize)
{
// This should probably be heap allocated in your program.
double d[subsetSize][numPoints];
for (size_t m = 0; m != numPoints; ++m)
d[0][m] = points[m].x * points[m].y;
for (size_t k = 1; k != subsetSize; ++k)
for (size_t m = k; m != numPoints; ++m)
for (size_t l = k - 1; l != m; ++l)
{
point_t const curr = points[m];
point_t const prev = points[l];
double const area = d[k - 1][l] + (curr.x - prev.x) * curr.y;
if (area > d[k][m]) // is a better subset
d[k][m] = area;
}
// The maximum area subset is now one of the subsets on the last row.
double result = 0.;
for (size_t m = subsetSize; m != numPoints; ++m)
if (d[subsetSize - 1][m] > result)
result = d[subsetSize - 1][m];
return result;
}
int main()
{
// I assume these are entered in sorted order, as explained in the answer.
point_t const points[5] = {
{0.029394902328, 0.951299438575},
{0.176318878234, 0.493630156084},
{0.235041868262, 0.438197791997},
{0.376508963445, 0.437693410334},
{0.948798695015, 0.352125307881},
};
printf("%f\n", maxAreaSubset(points, 5, 3));
}
Using the example data you've provided, I find an optimal result of 0.381411, as desired.
From what I can tell, you and I both use the same method to calculate the area, as well as the overall concept, but my code seems to be returning a correct result. Perhaps reviewing it can help you find a discrepancy.
JavaScript code:
function f(pts, k){
// Sort the points by x
pts.sort(([a1, b1], [a2, b2]) => a1 - a2);
const n = pts.length;
let best = 0;
// m[k][j] represents the optimal
// value if the jth point is chosen
// as rightmost for k points
let m = new Array(k + 1);
// Initialise m
for (let i=1; i<=k; i++)
m[i] = new Array(n);
for (let i=0; i<n; i++)
m[1][i] = pts[i][0] * pts[i][1];
// Build the table
for (let i=2; i<=k; i++){
for (let j=i-1; j<n; j++){
m[i][j] = 0;
for (let jj=j-1; jj>=i-2; jj--){
const area = (pts[j][0] - pts[jj][0]) * pts[j][1];
m[i][j] = Math.max(m[i][j], area + m[i-1][jj]);
}
best = Math.max(best, m[i][j]);
}
}
return best;
}
var pts = [
[0.376508963445, 0.437693410334],
[0.948798695015, 0.352125307881],
[0.176318878234, 0.493630156084],
[0.029394902328, 0.951299438575],
[0.235041868262, 0.438197791997]
];
var k = 3;
console.log(f(pts, k));

array to pointer issue in C program

Here is the program which i am working on.
void primMST(int graph[N][N])
{
int parent[N] ; // Array to store constructed MST
int key[N]; // Key values used to pick minimum weight edge in cut
bool mstSet[N]; // To represent set of vertices not yet included in MST
int i, count, v;
// Initialize all keys as INFINITE
for (i = 0; i < N; i++)
key[i] = INT_MAX, mstSet[i] = false;
// Always include first 1st vertex in MST.
key[0] = 0; // Make key 0 so that this vertex is picked as first vertex
parent[0] = -1; // First node is always root of MST
// The MST will have N vertices
for (count = 0; count < N-1; count++)
{
// Pick thd minimum key vertex from the set of vertices
// not yet included in MST
int u = minKey(key, mstSet);
// Add the picked vertex to the MST Set
mstSet[u] = true;
// Update key value and parent index of the adjacent vertices of
// the picked vertex. Consider only those vertices which are not yet
// included in MST
for (v = 0; v < N; v++)
// graph[u][v] is non zero only for adjacent vertices of m
// mstSet[v] is false for vertices not yet included in MST
// Update the key only if graph[u][v] is smaller than key[v]
if (graph[u][v] && mstSet[v] == false && graph[u][v] < key[v])
parent[v] = u, key[v] = graph[u][v];
}
// print the constructed MST
printMST(parent, N, graph);
}
int main()
{
int i, j;
int** graph = (int**) malloc(sizeof(int*)*N);
for(i=0;i<N;i++)
graph[i] = (int*) malloc(sizeof(int)*N);
FILE *fp;
fp = fopen("AdjacencyMatrix_of_Graph_G_N.txt","r");
char c;
for(i=0;i<N;i++) {
for(j = 0; j < N; j++) {
fscanf(fp, "%c ", &c);
graph[i][j] = c-'0';
}
}
for(i=0;i<N;i++) {
for(j=0;j<N;j++) {
printf("%d ",graph[i][j]);
}
printf("\n");
}
primMST(graph);
fclose(fp);
return 0;
}
And i am getting the following warnings.
C:\TURBOC3\BIN\PROJECT\MST.c:125:10: warning: passing argument 1 of 'primMST' from incompatible pointer type
primMST(graph);
^
C:\TURBOC3\BIN\PROJECT\MST.c:59:6: note: expected 'int (*)[30]' but argument is of type 'int **'
void primMST(int graph[N][N])
^
Compilation results...
--------
- Errors: 0
- Warnings: 2
- Output Filename: C:\TURBOC3\BIN\PROJECT\MST.exe
- Output Size: 132.0068359375 KiB
- Compilation Time: 0.48s
as people have commented here, and int ** is not the same as int[][], and that is why the compiler complains.
also i can see that you are dynamically allocating a size of N array, this has 2 drawbacks:
1. malloc is a pretty expensive operation and calling it N times seem unnecessary.
2. the result will not be a continuous block of memory.
assuming that N is a #define, i would suggest allocating graph[N][N] on the stack in main() rather than dynamically allocating it.

Reachability in graph - C

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);
}

I'm trying to store path in Dijkstra's algorithm

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.

Modifying Dijkstra's Algorithm to an A* implementation

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].

Resources