@@ -302,3 +302,135 @@ static PyObject* minimum_spanning_tree_prim_adjacency_list(PyObject* self, PyObj
302
302
}
303
303
return reinterpret_cast <PyObject*>(mst);
304
304
}
305
+
306
+ static PyObject* shortest_paths_dijkstra_adjacency_list (PyObject* self, PyObject* args, PyObject* kwargs) {
307
+ PyObject* graph_obj;
308
+ const char * source_name;
309
+ const char * target_name = " " ;
310
+
311
+ static const char * kwlist[] = {" graph" , " source_node" , " target_node" , nullptr };
312
+ if (!PyArg_ParseTupleAndKeywords (args, kwargs, " O!s|s" , const_cast <char **>(kwlist),
313
+ &AdjacencyListGraphType, &graph_obj,
314
+ &source_name, &target_name)) {
315
+ return nullptr ;
316
+ }
317
+
318
+ AdjacencyListGraph* graph = reinterpret_cast <AdjacencyListGraph*>(graph_obj);
319
+
320
+ const size_t V = graph->node_map .size ();
321
+
322
+ std::unordered_map<std::string, double > dist;
323
+ std::unordered_map<std::string, std::string> pred;
324
+
325
+ for (const auto & [name, node] : graph->node_map ) {
326
+ dist[name] = std::numeric_limits<double >::infinity ();
327
+ pred[name] = " " ;
328
+ }
329
+ dist[source_name] = 0.0 ;
330
+
331
+ using PQEntry = std::pair<double , std::string>;
332
+ std::priority_queue<PQEntry, std::vector<PQEntry>, std::greater<>> pq;
333
+ pq.push ({0.0 , source_name});
334
+
335
+ while (!pq.empty ()) {
336
+ auto [u_dist, u_name] = pq.top (); pq.pop ();
337
+
338
+ if (u_dist > dist[u_name]) continue ;
339
+
340
+ AdjacencyListGraphNode* u = graph->node_map [u_name];
341
+ for (const auto & [v_name, _] : u->adjacent ) {
342
+ std::string edge_key = make_edge_key (u_name, v_name);
343
+ auto edge_it = graph->edges .find (edge_key);
344
+ if (edge_it == graph->edges .end ()) continue ;
345
+
346
+ GraphEdge* edge = edge_it->second ;
347
+ double weight = 0.0 ;
348
+ if (edge->value_type == DataType::Int)
349
+ weight = static_cast <double >(std::get<int64_t >(edge->value ));
350
+ else if (edge->value_type == DataType::Double)
351
+ weight = std::get<double >(edge->value );
352
+ else
353
+ continue ;
354
+
355
+ if (weight < 0 ) continue ;
356
+
357
+ double new_dist = dist[u_name] + weight;
358
+ if (new_dist < dist[v_name]) {
359
+ dist[v_name] = new_dist;
360
+ pred[v_name] = u_name;
361
+ pq.push ({new_dist, v_name});
362
+ }
363
+ }
364
+ }
365
+
366
+ PyObject* dist_dict = PyDict_New ();
367
+ PyObject* pred_dict = PyDict_New ();
368
+ if (!dist_dict || !pred_dict) return nullptr ;
369
+
370
+ for (const auto & [v, d] : dist) {
371
+ PyObject* dval = PyFloat_FromDouble (d);
372
+ if (!dval || PyDict_SetItemString (dist_dict, v.c_str (), dval) < 0 ) {
373
+ Py_XDECREF (dval);
374
+ Py_DECREF (dist_dict);
375
+ Py_DECREF (pred_dict);
376
+ return nullptr ;
377
+ }
378
+ Py_DECREF (dval);
379
+ }
380
+
381
+ for (const auto & [v, p] : pred) {
382
+ PyObject* py_pred;
383
+ if (p.empty ()) {
384
+ Py_INCREF (Py_None);
385
+ py_pred = Py_None;
386
+ } else {
387
+ py_pred = PyUnicode_FromString (p.c_str ());
388
+ if (!py_pred) {
389
+ Py_DECREF (dist_dict);
390
+ Py_DECREF (pred_dict);
391
+ return nullptr ;
392
+ }
393
+ }
394
+
395
+ if (PyDict_SetItemString (pred_dict, v.c_str (), py_pred) < 0 ) {
396
+ Py_DECREF (py_pred);
397
+ Py_DECREF (dist_dict);
398
+ Py_DECREF (pred_dict);
399
+ return nullptr ;
400
+ }
401
+ Py_DECREF (py_pred);
402
+ }
403
+
404
+ if (strlen (target_name) > 0 ) {
405
+ PyObject* out = PyTuple_New (2 );
406
+ if (!out) {
407
+ Py_DECREF (dist_dict);
408
+ Py_DECREF (pred_dict);
409
+ return nullptr ;
410
+ }
411
+
412
+ PyObject* dist_val = PyFloat_FromDouble (dist[target_name]);
413
+ if (!dist_val) {
414
+ Py_DECREF (out);
415
+ Py_DECREF (dist_dict);
416
+ Py_DECREF (pred_dict);
417
+ return nullptr ;
418
+ }
419
+
420
+ PyTuple_SetItem (out, 0 , dist_val);
421
+ PyTuple_SetItem (out, 1 , pred_dict);
422
+ Py_DECREF (dist_dict);
423
+ return out;
424
+ }
425
+
426
+ PyObject* result = PyTuple_New (2 );
427
+ if (!result) {
428
+ Py_DECREF (dist_dict);
429
+ Py_DECREF (pred_dict);
430
+ return nullptr ;
431
+ }
432
+
433
+ PyTuple_SetItem (result, 0 , dist_dict);
434
+ PyTuple_SetItem (result, 1 , pred_dict);
435
+ return result;
436
+ }
0 commit comments