Skip to content

Commit ac0c52e

Browse files
astar
1 parent 710e43e commit ac0c52e

File tree

5 files changed

+388
-22
lines changed

5 files changed

+388
-22
lines changed

0x07-c_pathfinding/2-dijkstra_graph.c

+21-21
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,17 @@ vertex_t *get_vertex_index(const graph_t *graph, size_t index)
3232
* get_smallest - A function that fetches index of vertex with smallest
3333
* tentative distance among the nodes in the unvisited
3434
* @graph: A pointer to the graph
35-
* @dist: The array to track the distances from start to a vertex
35+
* @dest: The array to track the distances from start to a vertex
3636
* @v: The array to track if vertex is visited or not
3737
* @index: The index with minimun identifying the vertex with minimum
3838
* tentative distance
3939
*
4040
* Return: minimum tentative distance among the nodes in the unvisited
4141
*/
42-
size_t get_smallest(graph_t *graph, size_t *dist, size_t *v, size_t *index)
42+
size_t get_smallest(graph_t *graph, size_t *dest, size_t *v, size_t *index)
4343
{
44-
size_t min = INFINITY;
45-
size_t *a = dist;
44+
size_t min = INF;
45+
size_t *a = dest;
4646
size_t i = 0;
4747

4848
while (i < V)
@@ -75,7 +75,7 @@ void loadQueue(graph_t *graph, queue_t *q, char **parent,
7575
vertex_t *v;
7676

7777
t = target->index;
78-
if (parent[t] || parent[start->index])
78+
if (parent[t])
7979
{
8080
queue_push_front(q, strdup(target->content));
8181
while (strcmp(parent[t], start->content))
@@ -102,33 +102,33 @@ void loadQueue(graph_t *graph, queue_t *q, char **parent,
102102
* @graph: The pointer to the graph to go through
103103
* @visited: The array to track if vertex is visited or not
104104
* @parent: The array to track parents of vertices
105-
* @dist: The array to track the distances from start to a vertex
105+
* @dest: The array to track the distances from start to a vertex
106106
* @start: A pointer to the starting vertex
107107
* @target: A pointer to the target vertex
108108
* @index: index of a current vertex tracked
109109
*/
110110
void findShortestPath(graph_t *graph, size_t *visited, char **parent,
111-
size_t *dist, const vertex_t *start,
111+
size_t *dest, const vertex_t *start,
112112
const vertex_t *target, size_t index)
113113
{
114114
vertex_t *curr, *child;
115115
edge_t *edge;
116-
size_t smallest = INFINITY, alt;
116+
size_t smallest = INF, alt;
117117

118118
curr = get_vertex_index(graph, index);
119119
if (!curr)
120120
return;
121121
edge = curr->edges;
122122
printf("Checking %s, distance from %s is %ld\n", curr->content,
123-
start->content, dist[index]);
123+
start->content, dest[index]);
124124
/*For the current node, consider all of its unvisited neighbors */
125125
while (edge && visited[index] == UNEXPLORED)
126126
{
127127
child = edge->dest;
128-
alt = dist[index] + edge->weight;
129-
if (child && (dist[child->index] > alt))
128+
alt = dest[index] + edge->weight;
129+
if (child && (dest[child->index] > alt))
130130
{
131-
dist[child->index] = dist[index] + edge->weight;
131+
dest[child->index] = dest[index] + edge->weight;
132132
if (parent[child->index])
133133
{
134134
free(parent[child->index]);
@@ -139,11 +139,11 @@ void findShortestPath(graph_t *graph, size_t *visited, char **parent,
139139
edge = edge->next;
140140
}
141141
visited[index] = EXPLORED;
142-
smallest = get_smallest(graph, dist, visited, &index);
143-
if (visited[target->index] == EXPLORED || smallest == INFINITY)
142+
smallest = get_smallest(graph, dest, visited, &index);
143+
if (visited[target->index] == EXPLORED || smallest == INF)
144144
return;
145145

146-
findShortestPath(graph, visited, parent, dist, start, target,
146+
findShortestPath(graph, visited, parent, dest, start, target,
147147
index);
148148
}
149149

@@ -161,27 +161,27 @@ queue_t *dijkstra_graph(graph_t *graph, vertex_t const *start,
161161
vertex_t const *target)
162162
{
163163
queue_t *q;
164-
size_t *dist, i, *visited;
164+
size_t *dest, i, *visited;
165165
char **parent;
166166

167167
if (graph != NULL)
168168
{
169169
q = queue_create();
170170
visited = (size_t *)malloc(graph->nb_vertices * sizeof(size_t));
171171
parent = (char **)malloc(graph->nb_vertices * sizeof(char *));
172-
dist = (size_t *) malloc(graph->nb_vertices * sizeof(size_t));
172+
dest = (size_t *) malloc(graph->nb_vertices * sizeof(size_t));
173173
for (i = 0; i < graph->nb_vertices; i++)
174174
{
175-
dist[i] = INFINITY; /*Assign to every node a tentative distance value */
175+
dest[i] = INF; /*Assign to every node a tentative distance value */
176176
visited[i] = UNEXPLORED; /*Mark all nodes visited. */
177177
parent[i] = NULL;
178178
}
179-
dist[start->index] = 0;
180-
findShortestPath(graph, visited, parent, dist, start, target,
179+
dest[start->index] = 0;
180+
findShortestPath(graph, visited, parent, dest, start, target,
181181
start->index);
182182
loadQueue(graph, q, parent, start, target);
183183
free(visited);
184-
free(dist);
184+
free(dest);
185185
for (i = 0; i < graph->nb_vertices; i++)
186186
{
187187
free(parent[i]);

0x07-c_pathfinding/3-a_star_graph.c

+212
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
#include "math.h"
2+
#include "pathfinding.h"
3+
4+
#define Euclidean(x1, y1, x2, y2) (sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2)))
5+
6+
/**
7+
* get_vertex_index - A function that fetches an vertex existing in graph by
8+
* name
9+
* @graph: A pointer to the graph
10+
* @index: The index identifying the vertex
11+
*
12+
* Return: vertex on success, NULL on failure
13+
*/
14+
vertex_t *get_vertex_index(const graph_t *graph, size_t index)
15+
{
16+
vertex_t *node;
17+
18+
if (index > graph->nb_vertices)
19+
return (NULL);
20+
node = graph->vertices;
21+
if (node == NULL)
22+
return (NULL);
23+
while (node != NULL)
24+
{
25+
if (node->index == index)
26+
{
27+
return (node);
28+
}
29+
node = node->next;
30+
}
31+
return (NULL);
32+
}
33+
34+
/**
35+
* get_smallest - A function that fetches index of vertex with smallest
36+
* tentative gScoreance among the nodes in the unvisited
37+
* @graph: A pointer to the graph
38+
* @fScore: The array to track the fScores
39+
* @v: The array to track if vertex is visited or not
40+
* @index: The index with minimun identifying the vertex with minimum
41+
* tentative gScoreance
42+
*
43+
* Return: minimum tentative gScoreance among the nodes in the unvisited
44+
*/
45+
size_t get_smallest(graph_t *graph, size_t *fScore, size_t *v, size_t *index)
46+
{
47+
size_t min = INF;
48+
size_t *a = fScore;
49+
size_t i = 0;
50+
51+
while (i < V)
52+
{
53+
if (*a < min && v[i] == UNEXPLORED)
54+
{
55+
min = *a;
56+
*index = i;
57+
}
58+
a++;
59+
i++;
60+
}
61+
return (min);
62+
}
63+
64+
/**
65+
* loadQueue - A function that loads the queue with vertices of shortest path
66+
* @graph: A pointer to the graph
67+
* @q: queue to be filled in
68+
* @cameFrom: The array to track cameFroms of vertices
69+
* @start: A pointer to the starting vertex
70+
* @target: A pointer to the target vertex
71+
*
72+
* Return: Nothing
73+
*/
74+
void loadQueue(graph_t *graph, queue_t *q, char **cameFrom,
75+
vertex_t const *start, vertex_t const *target)
76+
{
77+
size_t i = 0, t = 0;
78+
vertex_t *v;
79+
80+
t = target->index;
81+
if (cameFrom[t])
82+
{
83+
queue_push_front(q, strdup(target->content));
84+
while (strcmp(cameFrom[t], start->content))
85+
{
86+
queue_push_front(q, strdup(cameFrom[t]));
87+
v = graph->vertices;
88+
for (i = 0; i < V && v; i++)
89+
{
90+
if (strcmp(v->content, cameFrom[t]) == 0)
91+
{
92+
t = i;
93+
break;
94+
}
95+
v = v->next;
96+
}
97+
}
98+
queue_push_front(q, strdup(start->content));
99+
}
100+
}
101+
102+
/**
103+
* findShortestPath - A function that searches for the shortest path from a
104+
* starting point to a target point in a graph using dijkstra algorithm
105+
* @graph: The pointer to the graph to go through
106+
* @visited: The array to track if vertex is visited or not
107+
* @cameFrom: The array to track cameFroms of vertices
108+
* @gScore: The array to track the distances from start to a vertex
109+
* @fScore: The array to track the Euclidean distances from start to a vertex
110+
* @start: A pointer to the starting vertex
111+
* @target: A pointer to the target vertex
112+
* @index: index of a current vertex tracked
113+
*/
114+
void findShortestPath(graph_t *graph, size_t *visited, char **cameFrom,
115+
size_t *gScore, size_t *fScore, const vertex_t *start,
116+
const vertex_t *target, size_t index)
117+
{
118+
vertex_t *curr, *neighbour;
119+
edge_t *edge;
120+
size_t smallest, tentative_gScore;
121+
122+
smallest = INF;
123+
curr = get_vertex_index(graph, index);
124+
if (!curr)
125+
return;
126+
edge = curr->edges;
127+
printf("Checking %s, distance to %s is %ld\n", curr->content,
128+
target->content, (size_t) Euclidean(curr->x, curr->y, target->x,
129+
target->y));
130+
/*For the current node, consider all of its unvisited neighbors */
131+
while (edge && visited[index] == UNEXPLORED)
132+
{
133+
neighbour = edge->dest;
134+
if (neighbour)
135+
{
136+
tentative_gScore = gScore[index] + edge->weight;
137+
if (gScore[neighbour->index] >= tentative_gScore)
138+
{
139+
gScore[neighbour->index] = tentative_gScore;
140+
fScore[neighbour->index] = gScore[neighbour->index] +
141+
Euclidean(neighbour->x, neighbour->y, target->x, target->y);
142+
if (cameFrom[neighbour->index])
143+
{
144+
free(cameFrom[neighbour->index]);
145+
cameFrom[neighbour->index] = NULL;
146+
}
147+
cameFrom[neighbour->index] = strdup(curr->content);
148+
}
149+
}
150+
edge = edge->next;
151+
}
152+
visited[index] = EXPLORED;
153+
smallest = get_smallest(graph, fScore, visited, &index);
154+
if (visited[target->index] == EXPLORED || smallest == INF)
155+
return;
156+
findShortestPath(graph, visited, cameFrom, gScore, fScore, start,
157+
target, index);
158+
}
159+
160+
/**
161+
* a_star_graph - A function that searches for the shortest cameFrom from a
162+
* starting point to a target point in a graph using A-star algorithm
163+
* @graph: The pointer to the graph to go through
164+
* @start: A pointer to the starting vertex
165+
* @target: A pointer to the target vertex
166+
* Return: A queue, in which each node is a point in the cameFrom from start to
167+
* target
168+
*/
169+
queue_t *a_star_graph(graph_t *graph, vertex_t const *start,
170+
vertex_t const *target)
171+
{
172+
queue_t *q;
173+
size_t *gScore, i, *visited, *fScore;
174+
char **cameFrom;
175+
176+
if (graph != NULL)
177+
{
178+
q = queue_create();
179+
visited =
180+
(size_t *) malloc(graph->nb_vertices * sizeof(size_t));
181+
cameFrom = (char **)malloc(graph->nb_vertices * sizeof(char *));
182+
gScore = (size_t *) malloc(graph->nb_vertices * sizeof(size_t));
183+
fScore = (size_t *) malloc(graph->nb_vertices * sizeof(size_t));
184+
for (i = 0; i < graph->nb_vertices; i++)
185+
{
186+
gScore[i] = INF;
187+
fScore[i] = INF; /*Assign to every node a tentative distance value */
188+
visited[i] = UNEXPLORED; /*Mark all nodes visited. */
189+
cameFrom[i] = NULL;
190+
}
191+
gScore[start->index] = 0; /*cost of going from start to start is zero. */
192+
fScore[start->index] =
193+
Euclidean(start->x, start->y, target->x, target->y);
194+
findShortestPath(graph, visited, cameFrom, gScore, fScore,
195+
start, target, start->index);
196+
loadQueue(graph, q, cameFrom, start, target);
197+
free(visited);
198+
free(gScore);
199+
free(fScore);
200+
for (i = 0; i < graph->nb_vertices; i++)
201+
{
202+
free(cameFrom[i]);
203+
}
204+
free(cameFrom);
205+
if (!q->front)
206+
{
207+
free(q);
208+
q = NULL;
209+
}
210+
}
211+
return (q);
212+
}

0x07-c_pathfinding/pathfinding.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#define UNEXPLORED '0'
1919
#define EXPLORED '1'
2020
#define BACKTRACK '2'
21-
#define INFINITY UINT_MAX
21+
#define INF UINT_MAX
2222
#define V graph->nb_vertices
2323
/**
2424
* struct point_s - Structure storing coordinates

0 commit comments

Comments
 (0)