static void discharge(MatrixT const &C, MatrixT &F, MatrixT &excess, MatrixT &height, MatrixT &seen, graphblas::IndexType u) { graphblas::IndexType num_nodes, cols; C.get_shape(num_nodes, cols); while (excess.get_value_at(0, u) > 0) { if (seen.get_value_at(0, u) < num_nodes) { graphblas::IndexType v = seen.get_value_at(0, u); if (((C.get_value_at(u, v) - F.get_value_at(u, v)) > 0) && (height.get_value_at(0, u) > height.get_value_at(0, v))) { push(C, F, excess, u, v); } else { seen.set_value_at(0, u, seen.get_value_at(0, u) + 1); } } else { relabel(C, F, height, u); seen.set_value_at(0, u, 0); } } }
void pretty_print_matrix(std::ostream &ostr, MatrixT const &mat) { IndexType rows, cols; mat.get_shape(rows, cols); typename MatrixT::ScalarType zero(mat.get_zero()); for (IndexType row = 0; row < rows; ++row) { ostr << ((row == 0) ? "[[" : " ["); if (cols > 0) { auto val = mat.get_value_at(row, 0); if (val == zero) ostr << " "; else ostr << val; } for (IndexType col = 1; col < cols; ++col) { auto val = mat.get_value_at(row, col); if (val == zero) ostr << ", "; else ostr << ", " << val; } ostr << ((row == rows - 1) ? "]]\n" : "]\n"); } }
void row_index_of(MatrixT &mat) { graphblas::IndexType rows, cols; mat.get_shape(rows, cols); for (IndexType i = 0; i < rows; ++i) { for (IndexType j = 0; j < cols; ++j) { auto mat_ij = mat.get_value_at(i, j); if (mat_ij != mat.get_zero()) { mat.set_value_at(i, j, i); } } } }
typename MatrixT::ScalarType sum(MatrixT const &m) { using T = typename MatrixT::ScalarType; graphblas::IndexType rows, cols; m.get_shape(rows, cols); T sum = static_cast<T>(0); for (graphblas::IndexType i = 0; i < rows; ++i) { for (graphblas::IndexType j = 0; j < cols; ++j) { sum += m[i][j]; } } return sum; }
static void relabel(MatrixT const &C, MatrixT const &F, MatrixT &height, graphblas::IndexType u) { using T = typename MatrixT::ScalarType; graphblas::IndexType num_nodes, cols; C.get_shape(num_nodes, cols); T min_height = std::numeric_limits<T>::max(); for (graphblas::IndexType v = 0; v < num_nodes; ++v) { if ((C.get_value_at(u, v) - F.get_value_at(u, v)) > 0) { T a = height.get_value_at(0, v); min_height = std::min(min_height, a); height.set_value_at(0, u, min_height + 1); } } }
typename MatrixT::ScalarType maxflow(MatrixT const &capacity, graphblas::IndexType source, graphblas::IndexType sink) { using T = typename MatrixT::ScalarType; graphblas::IndexType rows, cols; capacity.get_shape(rows,cols); graphblas::IndexType num_nodes = rows; MatrixT flow(rows,cols); MatrixT height(1, num_nodes); MatrixT excess(1, num_nodes); MatrixT seen(1, num_nodes); std::vector<graphblas::IndexType> list; for (graphblas::IndexType i = 0; i < num_nodes; ++i) { if ((i != source) && (i != sink)) { list.push_back(i); } } height.set_value_at(0, source, num_nodes); excess.set_value_at(0, source, std::numeric_limits<T>::max()); for (graphblas::IndexType i = 0; i < num_nodes; ++i) { push(capacity, flow, excess, source, i); } graphblas::IndexType p = 0; while (p < (num_nodes - 2)) { graphblas::IndexType u = list[p]; T old_height = height.get_value_at(0, u); discharge(capacity, flow, excess, height, seen, u); if (height.get_value_at(0, u) > old_height) { graphblas::IndexType t = list[p]; list.erase(list.begin() + p); list.insert(list.begin() + 0, t); p = 0; } else { p += 1; } } T maxflow = static_cast<T>(0); for (graphblas::IndexType i = 0; i < num_nodes; ++i) { maxflow += flow.get_value_at(source, i); } return maxflow; }