///|
fn augment_matching(
  e : Int32,
  adjacency : Array[Array[Int32]],
  matched : Array[Int32],
  seen : Array[Bool],
) -> Bool {
  for r in adjacency[e] {
    if !seen[r] {
      seen[r] = true
      if matched[r] < 0 ||
        augment_matching(matched[r], adjacency, matched, seen) {
        matched[r] = e
        return true
      }
    }
  }
  false
}

///|
/// Ground elements are left vertices; a set is independent iff matchable.
pub fn Matroid::transversal(
  rights : Int32,
  neighbors : Array[Array[Int32]],
) -> Matroid raise MatroidError {
  check_size(neighbors.length())
  if rights < 0 || rights > 256 {
    raise InvalidInput("right vertices outside 0..256")
  }
  let owned = []
  for row in neighbors {
    owned.push(checked_set(rights, row))
  }
  {
    size: owned.length(),
    model: "transversal",
    evaluate: xs => {
      let matched = Array::make(rights, -1)
      let mut rank = 0
      for e in xs {
        if augment_matching(e, owned, matched, Array::make(rights, false)) {
          rank = rank + 1
        }
      }
      rank
    },
  }
}