Description
A "signaling accumulator" would be a useful concept for many graph algorithms where you want to keep track of whether an update has occurred in each iteration.
For example, in SSSP, we can test whether the algorithm has converged by checking whether any new updates were made to the distance vector during this iteration. Traditionally, you'd check this by performing an additional subtraction, or else otherwise checking whether the new distance vector has any new, shorter distances. Alternately, you could implement a new min
operator that sets a flag if there's an update. If no update occurs, the algorithm has converged, and the algorithm can end.
bool updated_value = false;
auto signaling_min = [&](auto&& a, auto&& b) {
auto min = grb::min{}(a, b);
if (min != a) {
updated_value = true;
return min;
};
auto update = grb::multiply(grb::transpose(a), dist,
grb::min{}, grb::plus{},
grb::full_vector_mask{});
auto dist2 = grb::ewise_union(dist, update, signaling_min);
if (!updated_value) {
break;
}
For GraphBLAS C++ 2.0, I would propose implementing a "signaling op" wrapper that indicates whether an update occurs when accumulating.
// Proposal for signal API
bool update
grb::signal min(grb::min{}, update);
template <typename Fn, typename Flag>
struct signal {
operator()(auto&& a, auto&& b) {
auto c = fn_(a, b);
if (c == a) {
flag_ = true;
}
return c;
}
Flag& flag_;
Fn fn_;
};