Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
matching.h
Go to the documentation of this file.
1#pragma once
2
3#include <concepts>
4#include <cstdint>
5#include <limits>
6#include <optional>
7#include <vector>
8
10
11namespace storm::utility {
12/*
13 * Finds a bijective mapping f: {0,...,n-1} -> {0,...,n-1} such that hasEdge(v, f(v)) is true for all v.
14 * If no such mapping exists, returns std::nullopt.
15 * The algorithm finds a maximum matching in the bipartite graph defined by hasEdge
16 */
17template<std::predicate<uint64_t, uint64_t> EdgePredicate>
18std::optional<std::vector<uint64_t>> findPerfectMatching(uint64_t const n, EdgePredicate&& hasEdge) {
19 // We follow Kuhn's augmenting path algorithm to find a maximum matching.
20 constexpr uint64_t None = std::numeric_limits<uint64_t>::max();
21 std::vector<uint64_t> f(n, None); // f[v] = image vertex assigned to v
22 storm::storage::BitVector available(n, true);
23 // Try to find an augmenting path that matches image vertex u.
24 // (The lambda takes itself as a parameter so it can recurse)
25 auto augment = [&](auto& self, uint64_t const u) -> bool {
26 for (uint64_t const v : available) {
27 if (hasEdge(v, u)) {
28 available.set(v, false);
29 // v is free, or its current partner can be re-matched elsewhere
30 if (f[v] == None || self(self, f[v])) {
31 f[v] = u;
32 return true;
33 }
34 }
35 }
36 return false;
37 };
38
39 // Match every image vertex (a matching saturating the image side).
40 for (uint64_t u = 0; u < n; ++u) {
41 available.fill();
42 if (!augment(augment, u)) {
43 return std::nullopt; // Hall's condition violated
44 }
45 }
46 return f;
47}
48} // namespace storm::utility
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
void fill()
Sets all bits from the bit vector.
std::optional< std::vector< uint64_t > > findPerfectMatching(uint64_t const n, EdgePredicate &&hasEdge)
Definition matching.h:18