Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding edge coloring algorithm for bipartite graphs (#1026)
### Summary This PR adds a graph edge-coloring algorithm ``graph_bipartite_edge_color`` for **bipartite** graphs based on the paper "A simple algorithm for edge-coloring bipartite multigraphs" by Noga Alon, 2003. The above function first checks whether the graph is indeed bipartite, and raises an exception of type ``GraphNotBipartite`` if this is not the case. Otherwise, the function edge-colors the graph and returns a dictionary with key being the edge index and value being the assigned color. This is the same output format as produced by other recently added edge-coloring functions ``graph_greedy_edge_color`` and ``graph_misra_gries_edge_color``. The algorithm uses exactly `d` colors when `d` is the maximum degree of a node in the graph. Usage example: ``` import rustworkx as rx graph = rx.generators.heavy_hex_graph(9) edge_colors = rx.graph_bipartite_edge_color(graph) num_colors = max(edge_colors.values()) + 1 assert num_colors == 3 ``` The algorithm has a runtime of `O(m log m)` where `m` is the number of edges in the graph. ### A few technical details: Internally this works with an undirected regular bipartite multigraph that - keeps an explicit partition of its nodes into "left nodes" and "right nodes" - only the edges connecting a left node to a right node are allowed (this is what _bipartite_ means) - each node in the graph has the same degree `r` (this is what _regular_ means) - each edge keeps additional data representing its _multiplicity_ (aka _weight_) and whether or not the edge is _bad_ (it is important that multiple edges connecting the same pairs of nodes are grouped into a single edges with multiplicity) The internal data structure for the above is called `RegularBipartiteMultiGraph`. I don't foresee it being used anywhere outside of this PR, and so it's not marked as ``pub``. There is one possible optimization that is mentioned in the paper but which I have not implemented. Let `r` be the maximum degree of a node in the original graph. If the original bipartite graph is not regular (i.e. some of its nodes have degree less than `r`), then extra vertices and edges are inserted to make it regular (and of degree `r`) with the final edge-coloring is obtained by restricting the edge-coloring of the multi-graph to original edges. In addition (this is the mentioned possible optimization), one could group multiple "left" vertices with total degree not exceeding `r` into a _single_ node in the multigraph; the same applies for subsets of right vertices. The implementation also contains a function ``euler_cycles`` that might be useful in general, however the flavor needed here is somewhat non-standard, and so I did not expose it. The standard definition assumes that the graph is connected and an _Euler cycle_ is a path that visits each edge exactly once and comes back to the starting vertex. In our case, however, the graph may be disconnected and the function ``euler_cycles`` returns a list of Euler cycles that visit each edge exactly once (however this is not an Euler cycle for the standard definition). * very messy initial implementation * adding random_bipartite_graph and some tests * tests * fix correctness checking functions * imports in test module * starting cleanup * minor * cleaning pass * fmt * fix for empty graphs * python tests + fmt * release notes * first round of clippy * clippy * minor * pylint * fmt * renaming * more renaming * api docs * release notes fix * correct release notes fix * yet another fix * Add Python type annotation to stub files * Fix stubs * adding python interface for creating random bipartite graphs, both directed and undirected * stubs * updating runtime complexity to include the number of nodes * derive(Clone) * panic! -> unreachable! * making bipartite_edge_color_with_partitions non-public, cleaning and polishing tests
- Loading branch information