-
-
Notifications
You must be signed in to change notification settings - Fork 395
New function : pgr maxWeightedMatching #3139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
bf976ae
6bb0f96
45aa881
e615c43
164fd0f
5913d65
148c7c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # This file is part of the pgRouting project. | ||
| # Copyright (c) 2017-2026 pgRouting developers | ||
| # License: GPL-2 See https://github.com/pgRouting/pgrouting/blob/main/LICENSE | ||
|
|
||
| set(LOCAL_FILES | ||
| mwm_graph.png | ||
| mwm_result.png | ||
| ) | ||
|
|
||
| foreach (f ${LOCAL_FILES}) | ||
| configure_file(${f} "${PGR_DOCUMENTATION_SOURCE_DIR}/images/${f}" COPYONLY) | ||
| list(APPEND LOCAL_IMG_FILES "${PGR_DOCUMENTATION_SOURCE_DIR}/images/${f}") | ||
| endforeach() | ||
|
|
||
| set(PROJECT_IMG_FILES ${PROJECT_IMG_FILES} ${LOCAL_IMG_FILES} PARENT_SCOPE) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,179 @@ | ||
| :file: This file is part of the pgRouting project. | ||
| :copyright: Copyright (c) 2020-2026 pgRouting developers | ||
| :license: Creative Commons Attribution-Share Alike 3.0 https://creativecommons.org/licenses/by-sa/3.0 | ||
|
|
||
| .. index:: | ||
| single: Flow Family ; pgr_maxWeightedMatching - Experimental | ||
| single: maxWeightedMatching - Experimental on v4.1 | ||
|
|
||
| | | ||
|
|
||
| ``pgr_maxWeightedMatching`` - Experimental | ||
| =============================================================================== | ||
|
|
||
| ``pgr_maxWeightedMatching`` — Calculates a maximum weighted matching in a graph. | ||
|
|
||
| .. include:: experimental.rst | ||
| :start-after: warning-begin | ||
| :end-before: end-warning | ||
|
|
||
| .. rubric:: Availability | ||
|
|
||
| .. rubric:: Version 4.1.0 | ||
|
|
||
| * New experimental function. | ||
|
|
||
|
|
||
| Description | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| A **maximum weighted matching** in a graph is a matching where the sum of the | ||
| weights of selected edges is maximized. | ||
|
|
||
| A matching or independent edge set in a graph is a set of edges without common | ||
| vertices. | ||
|
|
||
| The main characteristics are: | ||
|
|
||
| - Works for **undirected** graphs. | ||
| - Each vertex is matched with at most one other vertex. | ||
| - Maximizes the total edge weight sum. | ||
| - There may be many maximum weighted matchings. | ||
|
|
||
| - Calculates one possible maximum weighted matching in a graph. | ||
|
|
||
| - Returns the matched pairs of vertices in the form of a set of | ||
| `(start_vid, end_vid, agg_cost)`. | ||
|
|
||
| - `start_vid` and `end_vid` are the endpoints of the matched edge. | ||
| - `agg_cost` is the weight of the matched edge. | ||
|
|
||
| - For the undirected graph, the results are symmetric. | ||
|
|
||
| - The `agg_cost` of `(u, v)` is the same as for `(v, u)`. | ||
|
Comment on lines
+51
to
+53
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Remove the symmetric-results claim. Line 51 states that result rows are symmetric. The function returns one row per matched edge, not both 🤖 Prompt for AI Agents |
||
|
|
||
| - Running time: :math:`O(n^3)` where :math:`n` is the number of vertices. | ||
|
|
||
| |Boost| Boost Graph Inside | ||
|
|
||
| Signatures | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| .. rubric:: Summary | ||
|
|
||
| .. admonition:: \ \ | ||
| :class: signatures | ||
|
|
||
| | pgr_maxWeightedMatching(`Edges SQL`_, ``directed``) | ||
|
|
||
| | Returns set of |matrix-result| | ||
| | OR EMPTY SET | ||
|
|
||
| :Example: Using all edges. | ||
|
|
||
| .. literalinclude:: maxWeightedMatching.queries | ||
| :start-after: -- q1 | ||
| :end-before: -- q2 | ||
|
|
||
| Parameters | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| .. include:: allpairs-family.rst | ||
| :start-after: edges_start | ||
| :end-before: edges_end | ||
|
|
||
| Optional parameters | ||
| ............................................................................... | ||
|
|
||
| .. list-table:: | ||
| :width: 81 | ||
| :widths: auto | ||
| :header-rows: 1 | ||
|
|
||
| * - Column | ||
| - Type | ||
| - Default | ||
| - Description | ||
| * - ``directed`` | ||
| - ``BOOLEAN`` | ||
| - ``false`` | ||
| - Ignored. The matching algorithm always works on **undirected** graphs. | ||
|
|
||
| Inner Queries | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| Edges SQL | ||
| ............................................................................... | ||
|
|
||
| .. include:: pgRouting-concepts.rst | ||
| :start-after: basic_edges_sql_start | ||
| :end-before: basic_edges_sql_end | ||
|
|
||
| Result columns | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| Set of |matrix-result| | ||
|
|
||
| .. list-table:: | ||
| :width: 81 | ||
| :widths: 12 14 60 | ||
| :header-rows: 1 | ||
|
|
||
| * - Column | ||
| - Type | ||
| - Description | ||
| * - ``start_vid`` | ||
| - ``BIGINT`` | ||
| - Identifier of the first end point vertex of the matched edge. | ||
| * - ``end_vid`` | ||
| - ``BIGINT`` | ||
| - Identifier of the second end point vertex of the matched edge. | ||
| * - ``agg_cost`` | ||
| - ``FLOAT`` | ||
| - Weight of the matched edge. | ||
|
|
||
| Additional Examples | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| .. raw:: html | ||
|
|
||
| <table style="width:100%; border:none; border-collapse:collapse;"> | ||
| <tr> | ||
| <td style="width:50%; text-align:center; padding:8px; border:none;"> | ||
| <strong>Before Matching</strong><br/> | ||
| <img src="_images/mwm_graph.png" alt="Sample graph before maximum weighted matching" style="max-width:100%;"/> | ||
| <p><em>Sample graph with 5 vertices and 6 weighted edges before matching.</em></p> | ||
| </td> | ||
| <td style="width:50%; text-align:center; padding:8px; border:none;"> | ||
| <strong>After Matching</strong><br/> | ||
| <img src="_images/mwm_result.png" alt="Sample graph after maximum weighted matching" style="max-width:100%;"/> | ||
| <p><em>Graph after maximum weighted matching: selected edges are highlighted.</em></p> | ||
| </td> | ||
| </tr> | ||
| </table> | ||
|
|
||
| .. image:: images/mwm_graph.png | ||
| :width: 0 | ||
|
|
||
| .. image:: images/mwm_result.png | ||
| :width: 0 | ||
|
|
||
| :Example: Maximum weighted matching on a custom 5-vertex graph. | ||
|
|
||
| .. literalinclude:: maxWeightedMatching.queries | ||
| :start-after: -- q2 | ||
| :end-before: -- q4 | ||
|
|
||
|
|
||
| See Also | ||
| ------------------------------------------------------------------------------- | ||
|
|
||
| * :doc:`flow-family` | ||
| * :doc:`sampledata` | ||
| * `Boost: maximum_weighted_matching | ||
| <https://www.boost.org/doc/libs/latest/libs/graph/doc/maximum_weighted_matching.html>`__ | ||
|
|
||
| .. rubric:: Indices and tables | ||
|
|
||
| * :ref:`genindex` | ||
| * :ref:`search` | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -59,9 +59,20 @@ To see all issues & pull requests closed by this release see the | |||||||||||||||||||||
|
|
||||||||||||||||||||||
| * :issue:`3101`: pgr_edgeColoring not building graph correctly | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| .. rubric:: New experimental functions. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| * Flow | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| * :issue:3136: pgr_maxWeightedMatching | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
Comment on lines
+62
to
67
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Add missing backticks to the Line 66 uses 🐛 Proposed fix- * :issue:3136: pgr_maxWeightedMatching
+ * :issue:`3136`: pgr_maxWeightedMatching📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| .. rubric:: Summary of changes by function | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| * pgr_maxWeightedMatching | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| .. include:: pgr_maxWeightedMatching.rst | ||||||||||||||||||||||
| :start-after: Version 4.1.0 | ||||||||||||||||||||||
| :end-before: Description | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| * pgr_edgeColoring | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| .. include:: pgr_edgeColoring.rst | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ set(LOCAL_FILES | |
| pushRelabel | ||
| maxFlowMinCost | ||
| maxFlowMinCost_Cost | ||
| maxWeightedMatching | ||
|
|
||
| ) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| /* :file: This file is part of the pgRouting project. | ||
| :copyright: Copyright (c) 2016-2026 pgRouting developers | ||
| :license: Creative Commons Attribution-Share Alike 3.0 https://creativecommons.org/licenses/by-sa/3.0 */ | ||
| /* -- q1 */ | ||
| SELECT * FROM pgr_maxWeightedMatching( | ||
| 'SELECT id, source, target, cost FROM edges', | ||
| false | ||
| ); | ||
|
|
||
| /* -- q2 */ | ||
| CREATE TABLE additional_sample_1 ( | ||
| id SERIAL PRIMARY KEY, | ||
| source INTEGER, | ||
| target INTEGER, | ||
| cost DOUBLE PRECISION, | ||
| reverse_cost DOUBLE PRECISION | ||
| ); | ||
|
|
||
| INSERT INTO additional_sample_1 (source, target, cost, reverse_cost) VALUES | ||
| (1, 2, 5, 5), | ||
| (2, 3, 1, 1), | ||
| (1, 3, 2, 2), | ||
| (2, 4, 4, 4), | ||
| (4, 5, 3, 3), | ||
| (3, 5, 6, 6); | ||
| SELECT * FROM pgr_maxWeightedMatching( | ||
| 'SELECT id, source, target, cost, reverse_cost FROM additional_sample_1', | ||
| false | ||
| ); | ||
|
|
||
| /* -- q4 */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| BEGIN; | ||
| BEGIN | ||
| SET client_min_messages TO NOTICE; | ||
| SET | ||
| /* :file: This file is part of the pgRouting project. | ||
| :copyright: Copyright (c) 2016-2026 pgRouting developers | ||
| :license: Creative Commons Attribution-Share Alike 3.0 https://creativecommons.org/licenses/by-sa/3.0 */ | ||
| /* -- q1 */ | ||
| SELECT * FROM pgr_maxWeightedMatching( | ||
| 'SELECT id, source, target, cost FROM edges', | ||
| false | ||
| ); | ||
| start_vid | end_vid | agg_cost | ||
| -----------+---------+---------- | ||
| 2 | 4 | 1 | ||
| 5 | 6 | 2 | ||
| 3 | 7 | 3 | ||
| 8 | 9 | 4 | ||
| 10 | 11 | 5 | ||
| 13 | 14 | 6 | ||
| 15 | 16 | 7 | ||
| 12 | 17 | 8 | ||
| (8 rows) | ||
|
|
||
| /* -- q2 */ | ||
| CREATE TABLE additional_sample_1 ( | ||
| id SERIAL PRIMARY KEY, | ||
| source INTEGER, | ||
| target INTEGER, | ||
| cost DOUBLE PRECISION, | ||
| reverse_cost DOUBLE PRECISION | ||
| ); | ||
| CREATE TABLE | ||
| INSERT INTO additional_sample_1 (source, target, cost, reverse_cost) VALUES | ||
| (1, 2, 5, 5), | ||
| (2, 3, 1, 1), | ||
| (1, 3, 2, 2), | ||
| (2, 4, 4, 4), | ||
| (4, 5, 3, 3), | ||
| (3, 5, 6, 6); | ||
| INSERT 0 6 | ||
| SELECT * FROM pgr_maxWeightedMatching( | ||
| 'SELECT id, source, target, cost, reverse_cost FROM additional_sample_1', | ||
| false | ||
| ); | ||
| start_vid | end_vid | agg_cost | ||
| -----------+---------+---------- | ||
| 1 | 2 | 5 | ||
| 3 | 5 | 11 | ||
| (2 rows) | ||
|
Comment on lines
+42
to
+50
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🔴 Critical | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Description: Inspect how agg_cost is computed/populated for maxWeightedMatching.
fd -a 'maxWeightedMatching' src include | xargs -I{} sh -c 'echo "== {} =="; rg -n -C5 "agg_cost|agg\\.cost|weight" {}'Repository: pgRouting/pgrouting Length of output: 2085 🏁 Script executed: #!/bin/bash
set -eu
for f in \
include/max_flow/maxWeightedMatching.hpp \
src/max_flow/maxWeightedMatching_process.cpp \
src/max_flow/maxWeightedMatching_process.h \
src/max_flow/maxWeightedMatching.c \
include/drivers/max_flow/maxWeightedMatching_driver.h \
include/drivers/maxWeightedMatching_driver.hpp \
docqueries/max_flow/maxWeightedMatching.pg \
docqueries/max_flow/maxWeightedMatching.result
do
if [ -f "$f" ]; then
echo "===== $f ====="
cat -n "$f"
fi
done
echo "===== relevant output-field definitions ====="
rg -n -C4 "from_vid|to_vid|agg_cost|IID_t_rt|maxweightedmatching" \
include src docqueries/max_flow/maxWeightedMatching.pgRepository: pgRouting/pgrouting Length of output: 50376 🏁 Script executed: #!/bin/bash
set -eu
echo "===== maxWeightedMatching call graph ====="
rg -n -C8 "do_maxWeightedMatching|pgr_do_maxWeightedMatching|maximumWeightedMatch|maxWeightedMatching" \
src include --glob '*maxWeightedMatching*' --glob '*.cpp' --glob '*.hpp' --glob '*.h'
echo "===== result record definition ====="
rg -n -C6 "struct IID_t_rt|typedef struct IID_t_rt|using IID_t_rt" include src
echo "===== graph construction ====="
cat -n src/cpp_common/undirectedHasCostBG.cpp | sed -n '40,125p'
cat -n include/cpp_common/undirectedHasCostBG.hpp | sed -n '45,100p'
echo "===== driver implementation candidates ====="
fd -a -e cpp -e hpp -e h src include | xargs rg -l "do_maxWeightedMatching|maximumWeightedMatch" | while read -r f; do
echo "===== $f ====="
rg -n -C12 "do_maxWeightedMatching|maximumWeightedMatch" "$f"
doneRepository: pgRouting/pgrouting Length of output: 40355 🏁 Script executed: #!/bin/bash
set -eu
echo "===== complete maxWeightedMatching driver body ====="
cat -n src/max_flow/maxWeightedMatching_driver.cpp | sed -n '47,135p'
echo "===== maxWeightedMatching documentation ====="
rg -n -C8 "maxWeightedMatching|agg_cost|weight of the matched edge" \
doc locale/en/LC_MESSAGES --glob '*maxWeightedMatching*' --glob '*.po' --glob '*.rst' --glob '*.md' 2>/dev/null || true
echo "===== maxWeightedMatching tests and fixtures ====="
rg -n -C6 "maxWeightedMatching|maximumWeightedMatch|additional_sample_1" \
. --glob '!build/**' --glob '!dist/**' --glob '!node_modules/**' \
--glob '*test*' --glob '*.pg' --glob '*.result' --glob '*.sql' 2>/dev/null | head -400Repository: pgRouting/pgrouting Length of output: 50375 Return each matched edge weight in 🤖 Prompt for AI Agents |
||
|
|
||
| /* -- q4 */ | ||
| ROLLBACK; | ||
| ROLLBACK | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
| edgeDisjointPaths.pg | ||
| maxFlowMinCost.pg | ||
| maxFlowMinCost_Cost.pg | ||
| maxWeightedMatching.pg | ||
| )] | ||
| }, | ||
| ); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the source documentation and regenerate derived artifacts.
In
doc/src/release_notes.rst, change:issue:3136:to:issue:\3136`:soNEWS.mdcontains the standard Markdown issue link. Indoc/max_flow/pgr_maxWeightedMatching.rst`, replace the Boost documentation link with the correct maximum weighted matching URL, then regenerate the affected derived documentation files.📍 Affects 2 files
NEWS.md#L41-L41(this comment)locale/pot/pgrouting_doc_strings.pot#L11287-L11287🤖 Prompt for AI Agents