AgentStack
SKILL verified MIT Self-run

Greedy Bipartite Matching

skill-cxcscmu-skilllearnbench-greedy-bipartite-matching · by cxcscmu

Implement greedy bipartite matching for pairing cluster centroids with expert annotations.

No reviews yet
0 installs
9 views
0.0% view→install

Install

$ agentstack add skill-cxcscmu-skilllearnbench-greedy-bipartite-matching

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Greedy Bipartite Matching? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Greedy Bipartite Matching

Overview

Greedy matching finds pairs between two sets of points by iteratively selecting the closest unmatched pair until no more matches are possible below a distance threshold.

Algorithm

  1. Compute pairwise distances between cluster centroids and expert points
  2. Repeatedly find the closest pair (centroid, expert point) below max_distance
  3. Mark both as matched and remove from consideration
  4. Continue until no more valid pairs can be found

Implementation

import numpy as np

def greedy_match(centroids, expert_points, max_distance=100):
    """
    Match centroids to expert points using greedy algorithm.

    Args:
        centroids: (n, 2) array of cluster centroids
        expert_points: (m, 2) array of expert annotations
        max_distance: Maximum distance for a valid match

    Returns:
        matched_pairs: List of (centroid_idx, expert_idx, distance) tuples
    """
    centroids = np.asarray(centroids)
    expert_points = np.asarray(expert_points)

    if len(centroids) == 0 or len(expert_points) == 0:
        return []

    # Compute Euclidean distances (always standard Euclidean for matching)
    distances = np.linalg.norm(
        centroids[:, np.newaxis, :] - expert_points[np.newaxis, :, :],
        axis=2
    )

    matched_pairs = []
    unmatched_centroids = set(range(len(centroids)))
    unmatched_experts = set(range(len(expert_points)))

    while unmatched_centroids and unmatched_experts:
        # Find closest unmatched pair
        min_dist = np.inf
        best_c_idx = None
        best_e_idx = None

        for c_idx in unmatched_centroids:
            for e_idx in unmatched_experts:
                dist = distances[c_idx, e_idx]
                if dist  max_distance:
            break

        # Record match and remove from unmatched sets
        matched_pairs.append((best_c_idx, best_e_idx, min_dist))
        unmatched_centroids.remove(best_c_idx)
        unmatched_experts.remove(best_e_idx)

    return matched_pairs

Computing Metrics from Matches

def compute_f1_and_delta(matched_pairs, num_centroids, num_expert_points):
    """
    Compute F1 score and average delta from matched pairs.

    Returns:
        f1: Precision-recall harmonic mean
        avg_delta: Average distance of matched pairs
    """
    if len(matched_pairs) == 0:
        return 0.0, np.nan

    # True positives = number of matches
    tp = len(matched_pairs)

    # False positives = unmatched centroids
    fp = num_centroids - tp

    # False negatives = unmatched expert points
    fn = num_expert_points - tp

    # Precision and recall
    precision = tp / (tp + fp) if (tp + fp) > 0 else 0.0
    recall = tp / (tp + fn) if (tp + fn) > 0 else 0.0

    # F1 score
    f1 = 2 * (precision * recall) / (precision + recall) if (precision + recall) > 0 else 0.0

    # Average delta (distance)
    avg_delta = np.mean([dist for _, _, dist in matched_pairs])

    return f1, avg_delta

Notes

  • Always use standard Euclidean distance for matching, not the custom clustering metric
  • The greedy approach is O(nm) per iteration, overall O(n² m²) worst case
  • For larger datasets, consider Hungarian algorithm for optimal matching

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.