Skip to content

Commit bb97a8e

Browse files
Prerak SinghPrerak Singh
authored andcommitted
added optimization to dijkstra and prim
1 parent a9bf4bc commit bb97a8e

File tree

4 files changed

+157
-119
lines changed

4 files changed

+157
-119
lines changed

pydatastructs/graphs/_backend/cpp/AdjacencyList.hpp

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ typedef struct {
1919
std::vector<AdjacencyListGraphNode *> nodes;
2020
std::unordered_map<std::string, GraphEdge*> edges;
2121
std::unordered_map<std::string, AdjacencyListGraphNode*> node_map;
22+
std::unordered_map<int, AdjacencyListGraphNode*> id_map;
23+
std::unordered_map<int, std::string> id_to_name;
24+
std::unordered_map<std::string, int> name_to_id;
25+
int next_id;
2226

2327
} AdjacencyListGraph;
2428

@@ -34,6 +38,9 @@ static void AdjacencyListGraph_dealloc(AdjacencyListGraph* self) {
3438
self->edges.clear();
3539

3640
self->node_map.clear();
41+
self->id_map.clear();
42+
self->id_to_name.clear();
43+
self->name_to_id.clear();
3744

3845
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
3946
}
@@ -46,38 +53,38 @@ static PyObject* AdjacencyListGraph_new(PyTypeObject* type, PyObject* args, PyOb
4653
new (&self->nodes) std::vector<AdjacencyListGraphNode*>();
4754
new (&self->edges) std::unordered_map<std::string, GraphEdge*>();
4855
new (&self->node_map) std::unordered_map<std::string, AdjacencyListGraphNode*>();
56+
new (&self->id_map) std::unordered_map<int, AdjacencyListGraphNode*>();
57+
new (&self->id_to_name) std::unordered_map<int, std::string>();
58+
new (&self->name_to_id) std::unordered_map<std::string, int>();
59+
60+
self->next_id = 0;
4961

5062
Py_ssize_t num_args = PyTuple_Size(args);
5163
for (Py_ssize_t i = 0; i < num_args; ++i) {
5264
PyObject* node_obj = PyTuple_GetItem(args, i);
5365
if (!PyObject_IsInstance(node_obj, (PyObject*)&AdjacencyListGraphNodeType)) {
5466
PyErr_SetString(PyExc_TypeError, "All arguments must be AdjacencyListGraphNode instances");
55-
56-
self->nodes.~vector();
57-
self->edges.~unordered_map();
58-
self->node_map.~unordered_map();
59-
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
6067
return NULL;
6168
}
6269

6370
AdjacencyListGraphNode* node = reinterpret_cast<AdjacencyListGraphNode*>(node_obj);
6471

6572
if (self->node_map.find(node->name) != self->node_map.end()) {
6673
PyErr_Format(PyExc_ValueError, "Duplicate node with name '%s'", node->name.c_str());
67-
68-
self->nodes.~vector();
69-
self->edges.~unordered_map();
70-
self->node_map.~unordered_map();
71-
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
7274
return NULL;
7375
}
7476

77+
node->internal_id = self->next_id++;
78+
7579
Py_INCREF(node);
7680
self->nodes.push_back(node);
7781
self->node_map[node->name] = node;
82+
self->id_map[node->internal_id] = node;
83+
self->id_to_name[node->internal_id] = node->name;
84+
self->name_to_id[node->name] = node->internal_id;
7885
}
79-
PyObject* impl_str = PyUnicode_FromString("adjacency_list");
8086

87+
PyObject* impl_str = PyUnicode_FromString("adjacency_list");
8188
if (PyObject_SetAttrString(reinterpret_cast<PyObject*>(self), "_impl", impl_str) < 0) {
8289
Py_DECREF(impl_str);
8390
PyErr_SetString(PyExc_RuntimeError, "Failed to set _impl attribute");
@@ -112,9 +119,14 @@ static PyObject* AdjacencyListGraph_add_vertex(AdjacencyListGraph* self, PyObjec
112119
return NULL;
113120
}
114121

122+
node->internal_id = self->next_id++;
123+
115124
Py_INCREF(node);
116125
self->nodes.push_back(node);
117126
self->node_map[node->name] = node;
127+
self->id_map[node->internal_id] = node;
128+
self->id_to_name[node->internal_id] = node->name;
129+
self->name_to_id[node->name] = node->internal_id;
118130

119131
Py_RETURN_NONE;
120132
}
@@ -126,17 +138,15 @@ static PyObject* AdjacencyListGraph_is_adjacent(AdjacencyListGraph* self, PyObje
126138
if (!PyArg_ParseTuple(args, "ss", &node1_name_c, &node2_name_c))
127139
return NULL;
128140

129-
std::string node1_name(node1_name_c);
130-
std::string node2_name(node2_name_c);
131-
132-
auto it1 = self->node_map.find(node1_name);
133-
if (it1 == self->node_map.end()) {
141+
auto it1 = self->name_to_id.find(node1_name_c);
142+
if (it1 == self->name_to_id.end()) {
134143
PyErr_SetString(PyExc_KeyError, "node1 not found");
135144
return NULL;
136145
}
137-
AdjacencyListGraphNode* node1 = it1->second;
146+
int id1 = it1->second;
147+
AdjacencyListGraphNode* node1 = self->id_map[id1];
138148

139-
if (node1->adjacent.find(node2_name) != node1->adjacent.end()) {
149+
if (node1->adjacent.find(node2_name_c) != node1->adjacent.end()) {
140150
Py_RETURN_TRUE;
141151
} else {
142152
Py_RETURN_FALSE;
@@ -156,13 +166,13 @@ static PyObject* AdjacencyListGraph_neighbors(AdjacencyListGraph* self, PyObject
156166
if (!PyArg_ParseTuple(args, "s", &node_name_c))
157167
return NULL;
158168

159-
std::string node_name(node_name_c);
160-
auto it = self->node_map.find(node_name);
161-
if (it == self->node_map.end()) {
169+
auto it = self->name_to_id.find(node_name_c);
170+
if (it == self->name_to_id.end()) {
162171
PyErr_SetString(PyExc_KeyError, "Node not found");
163172
return NULL;
164173
}
165-
AdjacencyListGraphNode* node = it->second;
174+
int id = it->second;
175+
AdjacencyListGraphNode* node = self->id_map[id];
166176

167177
PyObject* neighbors_list = PyList_New(0);
168178
if (!neighbors_list) return NULL;
@@ -180,23 +190,27 @@ static PyObject* AdjacencyListGraph_remove_vertex(AdjacencyListGraph* self, PyOb
180190
if (!PyArg_ParseTuple(args, "s", &name_c))
181191
return NULL;
182192

183-
std::string name(name_c);
184-
auto it = self->node_map.find(name);
185-
if (it == self->node_map.end()) {
193+
auto it = self->name_to_id.find(name_c);
194+
if (it == self->name_to_id.end()) {
186195
PyErr_SetString(PyExc_KeyError, "Node not found");
187196
return NULL;
188197
}
189198

190-
AdjacencyListGraphNode* node_to_remove = it->second;
199+
int id = it->second;
200+
AdjacencyListGraphNode* node_to_remove = self->id_map[id];
201+
std::string name = node_to_remove->name;
191202

192203
auto& nodes_vec = self->nodes;
193204
nodes_vec.erase(std::remove(nodes_vec.begin(), nodes_vec.end(), node_to_remove), nodes_vec.end());
194205

195-
self->node_map.erase(it);
206+
self->node_map.erase(name);
207+
self->id_map.erase(id);
208+
self->name_to_id.erase(name);
209+
self->id_to_name.erase(id);
196210

197211
Py_XDECREF(node_to_remove);
198212

199-
for (auto& node_pair : self->node_map) {
213+
for (auto& node_pair : self->id_map) {
200214
AdjacencyListGraphNode* node = node_pair.second;
201215
auto adj_it = node->adjacent.find(name);
202216
if (adj_it != node->adjacent.end()) {
@@ -207,17 +221,11 @@ static PyObject* AdjacencyListGraph_remove_vertex(AdjacencyListGraph* self, PyOb
207221

208222
for (auto it = self->edges.begin(); it != self->edges.end(); ) {
209223
const std::string& key = it->first;
210-
211-
bool involves_node = false;
212224
size_t underscore = key.find('_');
213-
if (underscore != std::string::npos) {
214-
std::string source = key.substr(0, underscore);
215-
std::string target = key.substr(underscore + 1);
216-
if (source == name || target == name)
217-
involves_node = true;
218-
}
225+
std::string src = key.substr(0, underscore);
226+
std::string dst = key.substr(underscore + 1);
219227

220-
if (involves_node) {
228+
if (src == name || dst == name) {
221229
Py_XDECREF(it->second);
222230
it = self->edges.erase(it);
223231
} else {

0 commit comments

Comments
 (0)