torressa / cspy

A collection of algorithms for the (Resource) Constrained Shortest Path problem in Python / C++ / C#
https://torressa.github.io/cspy/
MIT License
77 stars 24 forks source link

Ability to select arbitrary source and sink #115

Open andrea-cassioli-maersk opened 1 year ago

andrea-cassioli-maersk commented 1 year ago

Is your feature request related to a problem? Please describe. I am always frustrated that I have to rename source and sink in order to fit cspy format. Moreover, it makes difficult to parallelise its execution.

Describe the solution you'd like I would like to have two optional parameters to set an alternative name for the source and/or sink

Describe alternatives you've considered NA

tomatoes-prog commented 1 year ago

I would like to know how does this affects the parallelization procces, I think it actually standardize the process and makes it easier

torressa commented 1 year ago

Thanks! @andrea-cassioli-maersk As @tomatoes-prog says, it's just a design choice that I made, as there were already quite a few function arguments. The C++ layer doesn't use this convention so this is easy to expose this to Python (but it relies on other assumptions such as integer node labels). To easily change the node names I am using nx.relabel_nodes. I am not sure how this affects any sort of parallel execution as it's a simple 1-1 mapping.

andrea-cassioli-maersk commented 1 year ago

@tomatoes-prog I guess I am missing some points, but how would you run in parallel searches from a number of source/target pairs?

torressa commented 1 year ago
import multiprocessing as mp

import networkx as nx

def run(input_data):
    G, source, sink = input_data
    G = nx.relabel_nodes(G, {source: "Source", sink: "Sink"}, copy=False)
    print(f"In run, mapping {source}->'Source', {sink} -> 'Sink'. Edges: {G.edges()}")

if __name__ == "__main__":
    G = nx.DiGraph()

    G.add_edge(0, 1)
    G.add_edge(2, 3)

    with mp.Pool() as pool:
        pool.map(run, [(G, 0, 1), (G, 2, 3)])

    print(f"Done: {G.edges()}")

Expected output:

In run, mapping 0->'Source', 1 -> 'Sink'. Edges: [(2, 3), ('Source', 'Sink')]
In run, mapping 2->'Source', 3 -> 'Sink'. Edges: [(0, 1), ('Source', 'Sink')]
Done: [(0, 1), (2, 3)]
andrea-cassioli-maersk commented 1 year ago

But you are not copying the graph, so each process will try to modify the source/sink, will it not?

andrea-cassioli-maersk commented 1 year ago

OK, I need to look a bit more into multiprocessing!

Given that the graph get copied, there is no issue, but still relabel_nodes would not be necessary if you can just pass source/sink!