@graphty/algorithms
Version:
Graph algorithms library for browser environments implemented in TypeScript
95 lines • 3.02 kB
JavaScript
import { bfsColoringWithPartitions } from "../traversal/bfs-variants.js";
/**
* Find maximum matching in a bipartite graph using augmenting path algorithm
* (simplified implementation that's more reliable than Hopcroft-Karp for this context)
*/
export function maximumBipartiteMatching(graph, options = {}) {
// If partitions not provided, try to infer them
let { leftNodes, rightNodes } = options;
if (!leftNodes || !rightNodes) {
const partition = bipartitePartition(graph);
if (!partition) {
throw new Error("Graph is not bipartite");
}
leftNodes = partition.left;
rightNodes = partition.right;
}
const matching = new Map();
const matchRight = new Map(); // Right to left matching
// Find augmenting paths using DFS
const visited = new Set();
const dfs = (u) => {
const neighbors = Array.from(graph.neighbors(u));
for (const v of neighbors) {
if (!rightNodes.has(v) || visited.has(v)) {
continue;
}
visited.add(v);
// If v is unmatched or we can find augmenting path from match of v
const matchedNode = matchRight.get(v);
if (!matchRight.has(v) || (matchedNode !== undefined && dfs(matchedNode))) {
matching.set(u, v);
matchRight.set(v, u);
return true;
}
}
return false;
};
// Try to find augmenting path for each left node
let matchingSize = 0;
for (const u of leftNodes) {
visited.clear();
if (dfs(u)) {
matchingSize++;
}
}
return {
matching,
size: matchingSize,
};
}
/**
* Check if graph is bipartite and return the partition
*/
export function bipartitePartition(graph) {
const result = bfsColoringWithPartitions(graph);
if (!result.isBipartite || !result.partitions) {
return null;
}
return {
left: result.partitions[0],
right: result.partitions[1],
};
}
/**
* Simple greedy bipartite matching algorithm
* Useful for comparison or when Hopcroft-Karp is overkill
*/
export function greedyBipartiteMatching(graph, options = {}) {
let { leftNodes, rightNodes } = options;
if (!leftNodes || !rightNodes) {
const partition = bipartitePartition(graph);
if (!partition) {
throw new Error("Graph is not bipartite");
}
leftNodes = partition.left;
rightNodes = partition.right;
}
const matching = new Map();
const matched = new Set();
for (const u of leftNodes) {
const neighbors = Array.from(graph.neighbors(u));
for (const v of neighbors) {
if (rightNodes.has(v) && !matched.has(v)) {
matching.set(u, v);
matched.add(v);
break;
}
}
}
return {
matching,
size: matching.size,
};
}
//# sourceMappingURL=bipartite.js.map