Skip to content

New feature: maximum matching of general graph - #2550

Open
elena-schafer wants to merge 51 commits into
igraph:developfrom
elena-schafer:EdmondsBlossom
Open

New feature: maximum matching of general graph#2550
elena-schafer wants to merge 51 commits into
igraph:developfrom
elena-schafer:EdmondsBlossom

Conversation

@elena-schafer

@elena-schafer elena-schafer commented Mar 28, 2024

Copy link
Copy Markdown

The new pull request after the issues with #2530

Fixes #2403

Egan Schafer and others added 30 commits January 22, 2024 08:57
Comment thread src/misc/matching.c
/**
* \function igraph_maximum_matching
* \brief Calculates a maximum matching in a graph.
*

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
*
*
* \experimental
*

Just so we don't forget.

@elena-schafer

Copy link
Copy Markdown
Author

The algorithm itself uses the m[v] = u approach internally, and it's probably necessary.
This makes me kinda favor the two output arguments approach, as we already have the one.
However this isn't the most clean for the weighted multigraph case as there's an argument that becomes unnecessary.

I'm really fine with either, and will get started implementing it once we decided this.

@szhorvat

Copy link
Copy Markdown
Member

We didn't forget this PR, just need to find the time to go over it. It's a non-trivial amount of work.

The m[v] = u approach is fine internally, but the interface can still be such that returning an edge set is possible.

Changing the interface is relatively easy. The first step of the review should be verifying correctness and performance.

@szhorvat szhorvat added this to the 1.0 milestone Apr 22, 2024

This comment was marked as outdated.

@szhorvat
szhorvat requested a review from Copilot June 29, 2025 20:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request introduces a new maximum matching feature for general graphs along with corresponding unit tests, example code, and build system updates.

  • Adds new unit tests (trivial, path, bipartite, general, and Petersen graphs) for the maximum matching functionality.
  • Implements the new maximum matching algorithm in src/misc/matching.c, including blossom contraction, with proper memory management using IGRAPH_FINALLY macros.
  • Updates CMakeLists.txt, header declarations, and example files to support the new functionality.

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/unit/igraph_maximum_matching.c Adds comprehensive tests for maximum matching on various graph types.
tests/CMakeLists.txt Updates test targets to include igraph_maximum_matching.
src/misc/matching.c Implements the new maximum matching algorithm with blossom contraction.
include/igraph_matching.h Updates header to export the igraph_maximum_matching function.
examples/simple/igraph_maximum_matching.c Provides an example usage of the maximum matching function.

Comment thread src/misc/matching.c Outdated
Comment thread src/misc/matching.c
Comment on lines +1100 to +1102
while (igraph_vector_int_size(&path) != 0) {
//augment
for (igraph_integer_t i = 0; i + 2 < igraph_vector_int_size(&path); i = i + 2) {

Copilot AI Jun 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Cache the result of igraph_vector_int_size(&path) in a local variable within the loop condition to avoid repeated calls, which can improve performance in cases where the vector size is invariant during the loop.

Suggested change
while (igraph_vector_int_size(&path) != 0) {
//augment
for (igraph_integer_t i = 0; i + 2 < igraph_vector_int_size(&path); i = i + 2) {
igraph_integer_t path_size = igraph_vector_int_size(&path);
while (path_size != 0) {
//augment
for (igraph_integer_t i = 0; i + 2 < path_size; i = i + 2) {

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this is almost correct. It is indeed good to save the vector length and avoid repeated igraph_vector_int_size() calls in the for loop. But of course the same shouldn't be done for the while loop, as the vector size keep changing there.

szhorvat and others added 2 commits June 29, 2025 21:00
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Comment thread src/misc/matching.c
return IGRAPH_SUCCESS;
}

void igraph_i_maximum_matching_get_tree_path(igraph_integer_t *current, igraph_vector_bool_t *f_is_root, igraph_vector_int_t *contraction,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is void instead of returning igraph_error_t and the push_back() calls within are not checked for errors. Are we certain that these push_back() calls cannot fail, i.e. are they acting on a vector with guaranteed sufficient reserved storage? If yes, this should be explained in a comment. If not, error checks are necessary.

Comment thread src/misc/matching.c
current = VECTOR(f_parent)[current];
}
current = w;
igraph_vector_int_resize(&temp_list, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally, all functions that return an error code must be protected using IGRAPH_CHECK.

Comment thread src/misc/matching.c
Comment on lines +1189 to +1190
IGRAPH_CHECK(igraph_vector_bool_init(&b_mark, n));
IGRAPH_FINALLY(igraph_vector_bool_destroy, &b_mark);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such pairs can be replaced with the more concise:

Suggested change
IGRAPH_CHECK(igraph_vector_bool_init(&b_mark, n));
IGRAPH_FINALLY(igraph_vector_bool_destroy, &b_mark);
IGRAPH_VECTOR_BOOL_INIT_FINALLY(&b_mark, n);

Boolean vector that are not resized can be replaced with a more space-efficient igraph_bitset_t. This is a minor nitpick that is better fixed only when everything else is addressed.

Comment thread examples/simple/igraph_maximum_matching.c Outdated
Comment thread tests/unit/igraph_maximum_matching.c Outdated
@szhorvat

Copy link
Copy Markdown
Member

I had a quick look while testing Copilot, but unfortunately I still don't have the capacity to review this PR in full at this moment. I hope that you are interested in coming back to it eventually, but there is no need to address the comments just yet.

@ntamas

ntamas commented Jul 25, 2025

Copy link
Copy Markdown
Member

This is not API-breaking so we do not need to merge this before the release of 1.0. Unscheduling from the milestone to keep things tidy.

@ntamas ntamas modified the milestones: 1.0, 1.0-maybe Jul 25, 2025
@szhorvat szhorvat modified the milestones: 1.0-maybe, 1.1 Sep 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants