@@ -231,7 +231,104 @@ PYBIND11_MODULE(dsf_cpp, m) {
231231 &dsf::mobility::RoadNetwork::addCoil,
232232 pybind11::arg (" streetId" ),
233233 pybind11::arg (" name" ) = std::string (),
234- dsf::g_docstrings.at (" dsf::mobility::RoadNetwork::addCoil" ).c_str ());
234+ dsf::g_docstrings.at (" dsf::mobility::RoadNetwork::addCoil" ).c_str ())
235+ .def (
236+ " shortestPath" ,
237+ [](const dsf::mobility::RoadNetwork& self,
238+ dsf::Id sourceId,
239+ dsf::Id targetId,
240+ dsf::PathWeight weightFunction,
241+ double threshold) {
242+ return self.shortestPath (
243+ sourceId,
244+ targetId,
245+ [weightFunction](const std::unique_ptr<dsf::mobility::Street>& street) {
246+ switch (weightFunction) {
247+ case dsf::PathWeight::LENGTH:
248+ return street->length ();
249+ case dsf::PathWeight::TRAVELTIME:
250+ return street->length () / street->maxSpeed ();
251+ case dsf::PathWeight::WEIGHT:
252+ return street->weight ();
253+ default :
254+ return street->length () / street->maxSpeed ();
255+ }
256+ },
257+ threshold);
258+ },
259+ pybind11::arg (" sourceId" ),
260+ pybind11::arg (" targetId" ),
261+ pybind11::arg (" weightFunction" ) = dsf::PathWeight::TRAVELTIME,
262+ pybind11::arg (" threshold" ) = 1e-9 ,
263+ " Find the shortest path between two nodes using Dijkstra's algorithm.\n\n "
264+ " Args:\n "
265+ " sourceId (int): The id of the source node\n "
266+ " targetId (int): The id of the target node\n "
267+ " weightFunction (PathWeight): The weight function to use (LENGTH, "
268+ " TRAVELTIME, or WEIGHT)\n "
269+ " threshold (float): A threshold value to consider alternative paths\n\n "
270+ " Returns:\n "
271+ " PathCollection: A map where each key is a node id and the value is a "
272+ " vector of next hop node ids toward the target" );
273+
274+ pybind11::class_<dsf::mobility::PathCollection>(mobility, " PathCollection" )
275+ .def (pybind11::init<>(), " Create an empty PathCollection" )
276+ .def (
277+ " __getitem__" ,
278+ [](const dsf::mobility::PathCollection& self, dsf::Id key) {
279+ auto it = self.find (key);
280+ if (it == self.end ()) {
281+ throw pybind11::key_error (" Key not found" );
282+ }
283+ return it->second ;
284+ },
285+ pybind11::arg (" key" ),
286+ " Get the next hops for a given node id" )
287+ .def (
288+ " __setitem__" ,
289+ [](dsf::mobility::PathCollection& self,
290+ dsf::Id key,
291+ std::vector<dsf::Id> value) { self[key] = value; },
292+ pybind11::arg (" key" ),
293+ pybind11::arg (" value" ),
294+ " Set the next hops for a given node id" )
295+ .def (
296+ " __contains__" ,
297+ [](const dsf::mobility::PathCollection& self, dsf::Id key) {
298+ return self.find (key) != self.end ();
299+ },
300+ pybind11::arg (" key" ),
301+ " Check if a node id exists in the collection" )
302+ .def (
303+ " __len__" ,
304+ [](const dsf::mobility::PathCollection& self) { return self.size (); },
305+ " Get the number of nodes in the collection" )
306+ .def (
307+ " keys" ,
308+ [](const dsf::mobility::PathCollection& self) {
309+ std::vector<dsf::Id> keys;
310+ keys.reserve (self.size ());
311+ for (const auto & [key, _] : self) {
312+ keys.push_back (key);
313+ }
314+ return keys;
315+ },
316+ " Get all node ids in the collection" )
317+ .def (
318+ " items" ,
319+ [](const dsf::mobility::PathCollection& self) {
320+ pybind11::dict items;
321+ for (const auto & [key, value] : self) {
322+ items[pybind11::int_ (key)] = pybind11::cast (value);
323+ }
324+ return items;
325+ },
326+ " Get all items (node id, next hops) in the collection" )
327+ .def (" explode" ,
328+ &dsf::mobility::PathCollection::explode,
329+ pybind11::arg (" sourceId" ),
330+ pybind11::arg (" targetId" ),
331+ dsf::g_docstrings.at (" dsf::mobility::PathCollection::explode" ).c_str ());
235332
236333 pybind11::class_<dsf::mobility::Itinerary>(mobility, " Itinerary" )
237334 .def (pybind11::init<dsf::Id, dsf::Id>(),
0 commit comments