Skip to content

Instantly share code, notes, and snippets.

@alcatrazEscapee
Last active May 26, 2021 12:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alcatrazEscapee/2a0b0dd8446cbf776fa7b300127d8075 to your computer and use it in GitHub Desktop.
Save alcatrazEscapee/2a0b0dd8446cbf776fa7b300127d8075 to your computer and use it in GitHub Desktop.
/*
* This code is licensed under CC0 1.0. Use it, do whatever you want with it!
*/
import java.util.List;
import java.util.function.Predicate;
public class PerfectMatchingWithEdmondsMatrix
{
/**
* Checks the existence of a <a href="https://en.wikipedia.org/wiki/Perfect_matching">perfect matching</a> of a <a href="https://en.wikipedia.org/wiki/Bipartite_graph">bipartite graph</a>.
* The graph is interpreted as the matches between the set of inputs, and the set of tests.
* This algorithm computes the <a href="https://en.wikipedia.org/wiki/Edmonds_matrix">Edmonds Matrix</a> of the graph, which has the property that the determinant is identically zero iff the graph does not admit a perfect matching.
*/
public static <T> boolean perfectMatchExists(List<T> inputs, List<? extends Predicate<T>> tests)
{
if (inputs.size() != tests.size())
{
return false;
}
final int size = inputs.size();
final boolean[][] matrices = new boolean[size][];
for (int i = 0; i < size; i++)
{
matrices[i] = new boolean[(size + 1) * (size + 1)];
}
final boolean[] matrix = matrices[size - 1];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
matrix[i + size * j] = tests.get(i).test(inputs.get(j));
}
}
return perfectMatchDet(matrices, size);
}
private static boolean perfectMatchDet(boolean[][] matrices, int size)
{
// matrix true = nonzero = matches
final boolean[] matrix = matrices[size - 1];
switch (size)
{
case 1:
return matrix[0];
case 2:
return (matrix[0] && matrix[3]) || (matrix[1] && matrix[2]);
default:
{
for (int c = 0; c < size; c++)
{
if (matrix[c])
{
perfectMatchSub(matrices, size, c);
if (perfectMatchDet(matrices, size - 1))
{
return true;
}
}
}
return false;
}
}
}
private static void perfectMatchSub(boolean[][] matrices, int size, int dc)
{
final int subSize = size - 1;
final boolean[] matrix = matrices[subSize], sub = matrices[subSize - 1];
for (int c = 0; c < subSize; c++)
{
final int c0 = c + (c >= dc ? 1 : 0);
for (int r = 0; r < subSize; r++)
{
sub[c + subSize * r] = matrix[c0 + size * (r + 1)];
}
}
}
}
@bryan-hoang
Copy link

Cool!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment