Skip to content

Commit ed204aa

Browse files
authored
Merge pull request #83 from Electrostat-Lab/tree-algorithms
[ElectroNetSoft/Arithmos] Graph Algorithms: Dijkstra's Path finding Algorithm
2 parents 235df57 + b7265b2 commit ed204aa

File tree

5 files changed

+477
-0
lines changed

5 files changed

+477
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#ifndef __DIJKSTRA_ALGO__
2+
#define __DIJKSTRA_ALGO__
3+
4+
#include <electrostatic/electronetsoft/algorithm/arithmos/graph/math_structs.h>
5+
#include <inttypes.h>
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <limits.h>
9+
#include <math.h>
10+
11+
#define __INFINITY INT_MAX
12+
13+
typedef struct dijkstra_processors (dijkstra_processors);
14+
typedef struct dijkstra_structure (dijkstra_structure);
15+
16+
struct dijkstra_processors {
17+
void (*initializing_vertices_processor)(dijkstra_structure *);
18+
void (*on_lesser_vertex_found)(dijkstra_structure *, path *);
19+
void (*lesser_vertex_retrieval_processor)(dijkstra_structure *, path *);
20+
void (*update_path_processor)(dijkstra_structure *);
21+
void (*dijkstra_destroy_processor)(dijkstra_structure *);
22+
};
23+
24+
struct dijkstra_structure {
25+
cellular_matrix *matrix;
26+
dijkstra_processors *processors;
27+
path *pd_path;
28+
int cell_length;
29+
};
30+
31+
/**
32+
* Starts the Dijkstra's shortest path finding algorithm between the [start]
33+
* vertex and the [end] vertex, saving the result in a path mathematical structure.
34+
*
35+
* @param d_struct the dijkstra-structure contains the input cellular matrix that is a
36+
* mathematical structure representing a graph
37+
* by storing weights for each vertex with respect to other vertices.
38+
* @param start the index of the start vertex.
39+
* @param end the index of the stop vertex.
40+
* @param out the output shortest path.
41+
* @return (1) for failure, or (0) otherwise.
42+
*/
43+
uint8_t dijkstra_start(dijkstra_structure *d_struct, int start, int end, path *out);
44+
45+
/**
46+
* Destroys the dynamically heap-allocated buffers referenced from the d-struct
47+
* memory addresses.
48+
*
49+
* @param d_struct the dijkstra-structure
50+
* @return (1) for failure, or (0) otherwise.
51+
*/
52+
uint8_t dijkstra_destroy(dijkstra_structure *d_struct);
53+
54+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#ifndef __MATH_STRUCTS_
2+
#define __MATH_STRUCTS_
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
typedef struct vertex (vertex);
9+
typedef struct path (path);
10+
typedef struct cellular_matrix (cellular_matrix);
11+
12+
struct vertex {
13+
void *data;
14+
int position;
15+
int is_visited;
16+
};
17+
18+
/**
19+
* @brief A mathematical structure representing a way to keep track of
20+
* the total distance (d) from a reference vertex (ρ).
21+
*
22+
* @note
23+
* <p>
24+
* The distance is stored in an integer block "position" on each vertex.
25+
* <p>
26+
* The "position" integer block indicates the distance from a reference vertex (ρ).
27+
*/
28+
struct path {
29+
vertex **vertices;
30+
void (*update)();
31+
int cell_length;
32+
};
33+
34+
struct cellular_matrix {
35+
vertex ***cells;
36+
};
37+
38+
#ifdef __cplusplus
39+
};
40+
#endif
41+
42+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#include <electrostatic/electronetsoft/algorithm/arithmos/graph/dijkstra.h>
2+
3+
static inline int dijkstra_init(dijkstra_structure *d_struct, path *pd_path, int start) {
4+
if (d_struct == NULL || pd_path == NULL || pd_path->vertices == NULL) {
5+
return -1;
6+
}
7+
fprintf(stdout, "dijkstra_init: Passed Sanity checks!\n");
8+
fprintf(stdout, "dijkstra_init: First item %p\n", pd_path->vertices + 1);
9+
for (int i = 0; i < d_struct->cell_length; i++) {
10+
(*pd_path->vertices)[i].position = __INFINITY;
11+
(*pd_path->vertices)[i].is_visited = 0;
12+
(*pd_path->vertices)[i].data = d_struct->matrix->cells[i][0]->data;
13+
if (d_struct->processors != NULL && d_struct->processors->initializing_vertices_processor != NULL) {
14+
d_struct->processors->initializing_vertices_processor(d_struct);
15+
}
16+
fprintf(stdout, "dijkstra_init: Processing for initialization!\n");
17+
}
18+
(*pd_path->vertices)[start].position = 0;
19+
20+
return 0;
21+
}
22+
23+
static inline int dijkstra_get_lesser(dijkstra_structure *d_struct, path *pd_path, int base_position, path *out) {
24+
if (d_struct == NULL || d_struct->matrix == NULL || pd_path == NULL || pd_path->vertices == NULL) {
25+
return -1;
26+
}
27+
int lesser_position = base_position;
28+
int vertex_index = -1;
29+
fprintf(stdout, "dijkstra_get_lesser: Passed Sanity checks!\n");
30+
31+
for (int v = 0; v < d_struct->cell_length; v++) {
32+
if ((*pd_path->vertices)[v].is_visited) {
33+
continue;
34+
}
35+
fprintf(stdout, "dijkstra_get_lesser: Processing: %d\n", (*pd_path->vertices)[v].position);
36+
37+
if ((*pd_path->vertices)[v].position < lesser_position) {
38+
lesser_position = (*pd_path->vertices)[v].position;
39+
vertex_index = v;
40+
if (d_struct->processors != NULL && d_struct->processors->lesser_vertex_retrieval_processor != NULL) {
41+
d_struct->processors->lesser_vertex_retrieval_processor(d_struct, out);
42+
}
43+
}
44+
fprintf(stdout, "dijkstra_get_lesser: Processing lesser distance algorithm!\n");
45+
}
46+
if (vertex_index != -1) {
47+
(*pd_path->vertices)[vertex_index].is_visited = 1;
48+
out->vertices[out->cell_length] = &(*pd_path->vertices)[vertex_index];
49+
out->cell_length += 1;
50+
if (d_struct->processors != NULL && d_struct->processors->on_lesser_vertex_found != NULL) {
51+
d_struct->processors->on_lesser_vertex_found(d_struct, out);
52+
}
53+
fprintf(stdout, "dijkstra_get_lesser: Lesser path found!\n");
54+
}
55+
return vertex_index;
56+
}
57+
58+
/**
59+
* Updates a position dependent path from a corresponding cell inside a cellular matrix; such that
60+
* the new values have a lesser total distance from the current vertex than its predecessor vertices.
61+
*/
62+
static inline uint8_t dijkstra_update_path_from_cell(dijkstra_structure *d_struct, int cell_index, path *pd_path) {
63+
if (d_struct == NULL || d_struct->matrix == NULL || d_struct->matrix->cells == NULL ||
64+
pd_path == NULL || pd_path->vertices == NULL) {
65+
return 0;
66+
}
67+
fprintf(stdout, "dijkstra_update_path_from_cell: Passed Sanity checks with %d!\n", cell_index);
68+
69+
for (int v = 0; v < d_struct->cell_length; v++) {
70+
if (d_struct->matrix->cells[cell_index][v]->position == __INFINITY
71+
|| (*pd_path->vertices)[v].is_visited) {
72+
continue;
73+
}
74+
75+
// update the distances with the lesser distance from the root node, aka. the one referred to from the "cell_index"
76+
if (d_struct->matrix->cells[cell_index][v]->position + (*pd_path->vertices)[cell_index].position
77+
< (*pd_path->vertices)[v].position) {
78+
79+
(*pd_path->vertices)[v].position =
80+
d_struct->matrix->cells[cell_index][v]->position + (*pd_path->vertices)[cell_index].position;
81+
82+
if (d_struct->processors != NULL && d_struct->processors->update_path_processor != NULL) {
83+
d_struct->processors->update_path_processor(d_struct);
84+
}
85+
}
86+
}
87+
return 0;
88+
}
89+
90+
91+
uint8_t dijkstra_start(dijkstra_structure *d_struct, int start, int end, path *out) {
92+
if (d_struct == NULL || d_struct->matrix == NULL ||
93+
d_struct->matrix->cells == NULL || out == NULL || out->vertices == NULL) {
94+
return 1;
95+
}
96+
fprintf(stdout, "dijkstra_start: Passed Sanity checks!\n");
97+
// initialize a position-dependent path
98+
vertex *vertexes = calloc(d_struct->cell_length, sizeof (vertex));
99+
100+
path *pd_path = calloc(1, sizeof (path));
101+
pd_path->vertices = &vertexes;
102+
pd_path->cell_length = d_struct->cell_length;
103+
104+
d_struct->pd_path = pd_path;
105+
fprintf(stdout, "dijkstra_start: Passed Allocation of pd-path!\n");
106+
if (pd_path->vertices == NULL) {
107+
perror("Error allocating the position-dependent list!");
108+
return 1;
109+
}
110+
dijkstra_init(d_struct, pd_path, start);
111+
// loop as long as the end vertex is not reached and the cell vertices are still available
112+
// loop V times, the number of vertices
113+
for (int v = 0; v < d_struct->cell_length; v++) {
114+
fprintf(stdout, "dijkstra_start: Processing updates!\n");
115+
int cell_index = dijkstra_get_lesser(d_struct, pd_path, __INFINITY, out);
116+
fprintf(stdout, "dijkstra_start: Selected Index %d\n", cell_index);
117+
if (cell_index == end) {
118+
fprintf(stdout, "dijkstra_start: Reached the destination!\n");
119+
break;
120+
}
121+
dijkstra_update_path_from_cell(d_struct, cell_index, pd_path);
122+
}
123+
}
124+
125+
uint8_t dijkstra_destroy(dijkstra_structure *d_struct) {
126+
if (d_struct == NULL || d_struct->pd_path == NULL || *(d_struct->pd_path->vertices) == NULL) {
127+
return 1;
128+
}
129+
130+
if (d_struct->processors != NULL && d_struct->processors->dijkstra_destroy_processor != NULL) {
131+
d_struct->processors->dijkstra_destroy_processor(d_struct);
132+
}
133+
134+
free(*(d_struct->pd_path->vertices));
135+
free(d_struct->pd_path);
136+
137+
return 0;
138+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#include <gtk/gtk.h>
2+
3+
#define INITIAL_GRID_SIZE 8
4+
5+
typedef struct {
6+
GtkWidget *grid;
7+
int grid_size;
8+
} AppData;
9+
10+
void create_grid(AppData *app_data) {
11+
// Remove all existing children from the grid
12+
GList *children = gtk_container_get_children(GTK_CONTAINER(app_data->grid));
13+
for (GList *iter = children; iter != NULL; iter = g_list_next(iter)) {
14+
gtk_widget_destroy(GTK_WIDGET(iter->data));
15+
}
16+
g_list_free(children);
17+
18+
// Create new buttons and attach them to the grid
19+
for (int i = 0; i < app_data->grid_size; ++i) {
20+
for (int j = 0; j < app_data->grid_size; ++j) {
21+
GtkWidget *button = gtk_button_new_with_label(g_strdup_printf("%d,%d", i, j));
22+
gtk_widget_set_size_request(button, 50, 50); // Set button size
23+
24+
// Apply a CSS class to the button
25+
gtk_widget_set_name(button, "grid-button");
26+
27+
gtk_grid_attach(GTK_GRID(app_data->grid), button, i, j, 1, 1);
28+
}
29+
}
30+
gtk_widget_show_all(app_data->grid);
31+
}
32+
33+
void apply_css(GtkWidget *widget, const char *css) {
34+
GtkCssProvider *provider = gtk_css_provider_new();
35+
gtk_css_provider_load_from_data(provider, css, -1, NULL);
36+
GtkStyleContext *context = gtk_widget_get_style_context(widget);
37+
gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
38+
g_object_unref(provider);
39+
}
40+
41+
void on_size_button_clicked(GtkButton *button, AppData *app_data) {
42+
GtkWidget *size_entry = g_object_get_data(G_OBJECT(button), "size_entry");
43+
const char *size_text = gtk_entry_get_text(GTK_ENTRY(size_entry));
44+
int new_size = atoi(size_text);
45+
if (new_size > 0) {
46+
app_data->grid_size = new_size;
47+
create_grid(app_data);
48+
}
49+
}
50+
51+
void on_combo_box_changed(GtkComboBoxText *combo_box, AppData *app_data) {
52+
const char *active_text = gtk_combo_box_text_get_active_text(combo_box);
53+
if (g_strcmp0(active_text, "Algorithm 1") == 0) {
54+
// Placeholder for Algorithm 1
55+
} else if (g_strcmp0(active_text, "Algorithm 2") == 0) {
56+
// Placeholder for Algorithm 2
57+
} else if (g_strcmp0(active_text, "Algorithm 3") == 0) {
58+
// Placeholder for Algorithm 3
59+
}
60+
}
61+
62+
int main(int argc, char *argv[]) {
63+
gtk_init(&argc, &argv);
64+
65+
AppData app_data = {0};
66+
app_data.grid_size = INITIAL_GRID_SIZE;
67+
68+
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
69+
gtk_window_set_title(GTK_WINDOW(window), "Algorithm Visualizer");
70+
gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
71+
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
72+
73+
GtkWidget *main_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
74+
gtk_container_add(GTK_CONTAINER(window), main_box);
75+
76+
GtkWidget *input_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
77+
gtk_box_pack_start(GTK_BOX(main_box), input_box, FALSE, FALSE, 0);
78+
79+
GtkWidget *size_label = gtk_label_new("Grid Size:");
80+
gtk_box_pack_start(GTK_BOX(input_box), size_label, FALSE, FALSE, 0);
81+
82+
GtkWidget *size_entry = gtk_entry_new();
83+
gtk_entry_set_text(GTK_ENTRY(size_entry), g_strdup_printf("%d", INITIAL_GRID_SIZE));
84+
gtk_box_pack_start(GTK_BOX(input_box), size_entry, FALSE, FALSE, 0);
85+
86+
GtkWidget *size_button = gtk_button_new_with_label("Set Size");
87+
g_object_set_data(G_OBJECT(size_button), "size_entry", size_entry);
88+
g_signal_connect(size_button, "clicked", G_CALLBACK(on_size_button_clicked), &app_data);
89+
gtk_box_pack_start(GTK_BOX(input_box), size_button, FALSE, FALSE, 0);
90+
91+
GtkWidget *combo_box = gtk_combo_box_text_new();
92+
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), "Select Algorithm");
93+
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), "Algorithm 1");
94+
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), "Algorithm 2");
95+
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), "Algorithm 3");
96+
g_signal_connect(combo_box, "changed", G_CALLBACK(on_combo_box_changed), &app_data);
97+
gtk_box_pack_start(GTK_BOX(input_box), combo_box, FALSE, FALSE, 0);
98+
99+
app_data.grid = gtk_grid_new();
100+
gtk_box_pack_start(GTK_BOX(main_box), app_data.grid, TRUE, TRUE, 0);
101+
102+
create_grid(&app_data);
103+
104+
// Apply CSS to the window
105+
const char *css = "#grid-button { background-color: #00008B; color: white; }";
106+
apply_css(window, css);
107+
108+
gtk_widget_show_all(window);
109+
gtk_main();
110+
111+
return 0;
112+
}

0 commit comments

Comments
 (0)