Skip to content

Commit 3cbe730

Browse files
authored
Merge pull request #84 from Electrostat-Lab/mst-graph-algorithm
[ElectroNetSoft/Arithmos] Minimum Spanning Tree (MST) Graph Algorithm - Prim-Janik
2 parents ed204aa + c8372d3 commit 3cbe730

File tree

7 files changed

+592
-1
lines changed

7 files changed

+592
-1
lines changed

electrostatic-sandbox-framework/electrostatic-core/src/include/electrostatic/electronetsoft/algorithm/arithmos/graph/dijkstra.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,22 @@
88
#include <limits.h>
99
#include <math.h>
1010

11-
#define __INFINITY INT_MAX
11+
#ifdef __cplusplus
12+
extern "C" {
13+
#endif
1214

1315
typedef struct dijkstra_processors (dijkstra_processors);
1416
typedef struct dijkstra_structure (dijkstra_structure);
1517

1618
struct dijkstra_processors {
1719
void (*initializing_vertices_processor)(dijkstra_structure *);
20+
1821
void (*on_lesser_vertex_found)(dijkstra_structure *, path *);
22+
1923
void (*lesser_vertex_retrieval_processor)(dijkstra_structure *, path *);
24+
2025
void (*update_path_processor)(dijkstra_structure *);
26+
2127
void (*dijkstra_destroy_processor)(dijkstra_structure *);
2228
};
2329

@@ -51,4 +57,8 @@ uint8_t dijkstra_start(dijkstra_structure *d_struct, int start, int end, path *o
5157
*/
5258
uint8_t dijkstra_destroy(dijkstra_structure *d_struct);
5359

60+
#ifdef __cplusplus
61+
};
62+
#endif
63+
5464
#endif

electrostatic-sandbox-framework/electrostatic-core/src/include/electrostatic/electronetsoft/algorithm/arithmos/graph/math_structs.h

+45
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#ifndef __MATH_STRUCTS_
22
#define __MATH_STRUCTS_
33

4+
#include <stddef.h>
5+
#include <inttypes.h>
6+
7+
#define __INFINITY INT_MAX
8+
49
#ifdef __cplusplus
510
extern "C" {
611
#endif
@@ -9,12 +14,42 @@ typedef struct vertex (vertex);
914
typedef struct path (path);
1015
typedef struct cellular_matrix (cellular_matrix);
1116

17+
// for edge-based implementation
18+
typedef struct edge_matrix (edge_matrix);
19+
typedef struct edge (edge);
20+
typedef struct edge_path (edge_path);
21+
22+
typedef struct graph_processors (graph_processors);
23+
24+
struct graph_processors {
25+
void (*graph_vertices_cell_traversed)(cellular_matrix *, vertex **, int);
26+
void (*graph_cellular_vertex_traversed)(cellular_matrix *, vertex *, int);
27+
void (*graph_cell_traversed)(edge_matrix *, edge **, int);
28+
void (*graph_cellular_edge_traversed)(edge_matrix *, edge *, int);
29+
void (*graph_edge_path_traversed)(edge_path *path, edge *, int);
30+
};
31+
1232
struct vertex {
1333
void *data;
1434
int position;
1535
int is_visited;
1636
};
1737

38+
struct edge {
39+
vertex *initial;
40+
vertex *terminal;
41+
void *metadata;
42+
int length;
43+
int is_traversed;
44+
int position; /* represents the position of the edge from the start vertex */
45+
/* ZERO if both are coincident; in this case the start vertex = the initial vertex */
46+
};
47+
48+
struct edge_path {
49+
edge **edges;
50+
int count;
51+
};
52+
1853
/**
1954
* @brief A mathematical structure representing a way to keep track of
2055
* the total distance (d) from a reference vertex (ρ).
@@ -35,6 +70,16 @@ struct cellular_matrix {
3570
vertex ***cells;
3671
};
3772

73+
struct edge_matrix {
74+
edge ***cells;
75+
int cell_length;
76+
};
77+
78+
uint8_t graph_iterate_edge_matrix(edge_matrix *matrix, graph_processors *processors);
79+
uint8_t graph_iterate_edge(edge_path *path, graph_processors *processors);
80+
uint8_t graph_iterate_cellular_matrix(cellular_matrix *matrix, graph_processors *processors);
81+
uint8_t graph_iterate_vertices(path *path, graph_processors *processors);
82+
3883
#ifdef __cplusplus
3984
};
4085
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#ifndef __PRIMS_ALGORITHM__
2+
#define __PRIMS_ALGORITHM__
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+
#ifdef __cplusplus
12+
extern "C" {
13+
#endif
14+
15+
typedef struct prim_processors (prim_processors);
16+
typedef struct prim_structure (prim_structure);
17+
18+
struct prim_processors {
19+
void (*initializing_vertices_processor)(prim_structure *);
20+
void (*on_lesser_vertex_found)(prim_structure *, edge_path *);
21+
void (*lesser_vertex_retrieval_processor)(prim_structure *, edge_path *, int);
22+
void (*update_path_processor)(prim_structure *);
23+
void (*prim_destroy_processor)(prim_structure *);
24+
};
25+
26+
struct prim_structure {
27+
edge_matrix *matrix;
28+
prim_processors *processors;
29+
edge_path *pd_path;
30+
int cell_length;
31+
};
32+
33+
uint8_t prim_start(prim_structure *p_struct, int start, int end, edge_path *out);
34+
uint8_t prim_destroy(prim_structure *p_struct);
35+
36+
#ifdef __cplusplus
37+
};
38+
#endif
39+
40+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <electrostatic/electronetsoft/algorithm/arithmos/graph/math_structs.h>
2+
3+
uint8_t graph_iterate_edge_matrix(edge_matrix *matrix, graph_processors *processors) {
4+
if (matrix == NULL || matrix->cells == NULL || processors == NULL) {
5+
return 1;
6+
}
7+
for (int c = 0; c < matrix->cell_length; c++) {
8+
edge **m_edge = matrix->cells[c];
9+
if (m_edge == NULL) {
10+
continue;
11+
}
12+
if (processors->graph_cell_traversed != NULL) {
13+
processors->graph_cell_traversed(matrix, m_edge, c);
14+
}
15+
for (int e = 0; e < matrix->cell_length; e++) {
16+
if (m_edge[e] == NULL) {
17+
continue;
18+
}
19+
if (processors->graph_cellular_edge_traversed != NULL) {
20+
processors->graph_cellular_edge_traversed(matrix, m_edge[e], e);
21+
}
22+
}
23+
}
24+
return 0;
25+
}
26+
27+
28+
uint8_t graph_iterate_edge(edge_path *path, graph_processors *processors) {
29+
if (path == NULL || path->edges == NULL || processors == NULL) {
30+
return 1;
31+
}
32+
for (int e = 0; e < path->count; e++) {
33+
if (path->edges[e] == NULL) {
34+
continue;
35+
}
36+
if (processors->graph_edge_path_traversed != NULL) {
37+
processors->graph_edge_path_traversed(path, path->edges[e], e);
38+
}
39+
}
40+
return 0;
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
#include <electrostatic/electronetsoft/algorithm/arithmos/graph/prim.h>
2+
3+
static inline int prim_init(prim_structure *p_struct, int start) {
4+
if (p_struct == NULL || p_struct->matrix == NULL || p_struct->pd_path == NULL ||
5+
p_struct->pd_path->edges == NULL) {
6+
fprintf(stdout, "prim_init: Not Passed Sanity checks!\n");
7+
return -1;
8+
}
9+
fprintf(stdout, "prim_init: Passed Sanity checks!\n");
10+
fprintf(stdout, "prim_init: First item %p\n",
11+
p_struct->matrix->cells[start][1]);
12+
for (int i = 0; i < p_struct->cell_length; i++) {
13+
// deep copy the relations with the first vertex!
14+
// leave the nullary edges uninitialized!
15+
if (p_struct->matrix->cells[start][i] != NULL) {
16+
p_struct->pd_path->edges[i] = p_struct->matrix->cells[start][i];
17+
}
18+
if (p_struct->processors != NULL &&
19+
p_struct->processors->initializing_vertices_processor != NULL) {
20+
p_struct->processors->initializing_vertices_processor(p_struct);
21+
}
22+
fprintf(stdout, "prim_init: Processing for initialization!\n");
23+
}
24+
return 0;
25+
}
26+
27+
static inline int prim_get_lesser(prim_structure *p_struct, int base_position, edge_path *out) {
28+
if (p_struct == NULL || p_struct->matrix == NULL || p_struct->pd_path == NULL ||
29+
p_struct->pd_path->edges == NULL) {
30+
return -1;
31+
}
32+
int lesser_position = base_position;
33+
int edge_index = -1;
34+
fprintf(stdout, "prim_get_lesser: Passed Sanity checks!\n");
35+
36+
for (int e = 0; e < p_struct->cell_length; e++) {
37+
// skip the traversed edge
38+
if (p_struct->pd_path->edges[e] == NULL || p_struct->pd_path->edges[e]->is_traversed) {
39+
continue;
40+
}
41+
fprintf(stdout, "prim_get_lesser: Processing: %s\n",
42+
(const char *)p_struct->pd_path->edges[e]->metadata);
43+
44+
if (p_struct->pd_path->edges[e]->length < lesser_position) {
45+
lesser_position = p_struct->pd_path->edges[e]->length;
46+
edge_index = e;
47+
if (p_struct->processors != NULL &&
48+
p_struct->processors->lesser_vertex_retrieval_processor != NULL) {
49+
p_struct->processors->lesser_vertex_retrieval_processor(p_struct, out, e);
50+
}
51+
}
52+
fprintf(stdout, "prim_get_lesser: Processing lesser distance algorithm!\n");
53+
}
54+
if (edge_index != -1) {
55+
p_struct->pd_path->edges[edge_index]->is_traversed = 1;
56+
out->edges[out->count] = p_struct->pd_path->edges[edge_index];
57+
out->count += 1;
58+
if (p_struct->processors != NULL &&
59+
p_struct->processors->on_lesser_vertex_found != NULL) {
60+
p_struct->processors->on_lesser_vertex_found(p_struct, out);
61+
}
62+
fprintf(stdout, "prim_get_lesser: Lesser path found!\n");
63+
}
64+
return edge_index;
65+
}
66+
67+
// erroneous
68+
static inline uint8_t prim_update_path_from_edge(prim_structure *p_struct,
69+
int edge_index) {
70+
if (p_struct == NULL || p_struct->matrix == NULL ||
71+
p_struct->matrix->cells == NULL || p_struct->pd_path == NULL ||
72+
p_struct->pd_path->edges == NULL) {
73+
return 0;
74+
}
75+
fprintf(stdout, "prim_update_path_from_edge: Passed Sanity checks with %d!\n",
76+
edge_index);
77+
78+
for (int v = 0; v < p_struct->matrix->cell_length; v++) {
79+
if (p_struct->matrix->cells[edge_index][v] == NULL) {
80+
continue;
81+
}
82+
83+
// update the position-dependent list if the old edge was not reachable, but
84+
// now available! OR if it was available, but now available with a lesser
85+
// distance
86+
if (p_struct->pd_path->edges[v] == NULL ||
87+
(!p_struct->pd_path->edges[v]->is_traversed &&
88+
p_struct->matrix->cells[edge_index][v]->length < p_struct->pd_path->edges[v]->length)) {
89+
p_struct->pd_path->edges[v] = p_struct->matrix->cells[edge_index][v];
90+
if (p_struct->processors != NULL &&
91+
p_struct->processors->update_path_processor != NULL) {
92+
p_struct->processors->update_path_processor(p_struct);
93+
}
94+
fprintf(stdout, "prim_update_path_from_edge: Updated paths!\n");
95+
}
96+
}
97+
return 0;
98+
}
99+
100+
static inline void graph_edge_print(edge_path *path, edge *p_edge, int index) {
101+
if (p_edge == NULL) {
102+
return;
103+
}
104+
fprintf(stdout, "PD List element = (%d, %s, %d, is_traversed: %d)\n", index,
105+
(const char *) p_edge->metadata, p_edge->length, p_edge->is_traversed);
106+
}
107+
108+
uint8_t prim_start(prim_structure *p_struct, int start, int end,
109+
edge_path *out) {
110+
if (p_struct == NULL || out == NULL) {
111+
return 1;
112+
}
113+
p_struct->pd_path = calloc(1, sizeof (edge_path));
114+
p_struct->pd_path->edges = calloc(p_struct->cell_length, sizeof(edge *));
115+
p_struct->pd_path->count = p_struct->cell_length;
116+
117+
prim_init(p_struct, start);
118+
for (int v = 0; v < p_struct->matrix->cell_length; v++) {
119+
int edge_index = prim_get_lesser(p_struct, __INFINITY, out);
120+
if (edge_index == end) {
121+
break;
122+
}
123+
prim_update_path_from_edge(p_struct, edge_index);
124+
}
125+
return 0;
126+
}
127+
128+
uint8_t prim_destroy(prim_structure *p_struct) {
129+
if (p_struct == NULL || p_struct->pd_path == NULL) {
130+
return 1;
131+
}
132+
133+
if (p_struct->processors != NULL &&
134+
p_struct->processors->prim_destroy_processor != NULL) {
135+
p_struct->processors->prim_destroy_processor(p_struct);
136+
}
137+
138+
free(p_struct->pd_path->edges);
139+
p_struct->pd_path->edges = NULL;
140+
141+
free(p_struct->pd_path);
142+
p_struct->pd_path = NULL;
143+
}

0 commit comments

Comments
 (0)