I've got a directed graph (N, A)
, where each node n[i]
has a value v[i]
and a threshold t[i]
. For each arrow (n[i], n[j])
, the invariant v[i] <= v[j]
holds. I need to efficiently implement the following operations:
increaseThreshold(i, x)
: Sett[i] = max(t[i], x)
. That's trivial and only for completeness here.increaseValue(i, x)
: Setv[i] = max(v[i], x)
and increase other values as needed so that the above invariant holds.evaluate(i)
: return true ifv[i] < t[i]
The most straightforward implementation would store v[i]
, t[i]
, and the outgoing arrows with each node. On increaseValue(i, x)
, it'd propagate the value along all outgoing arrows (using a set of "open" nodes like many other graph algorithms do). With v[i]
stored with each node, evaluate(i)
is trivial.
As increaseValue
is much more frequent than the other operations, this eager approach seems to be wasteful. So I wonder, if some lazy propagation where v[i]
is recomputed as needed could be more efficient. For this, I'd maintain w[i]
as the maximum of all x
from increaseValue(i, x)
and compute v[j]
on the fly when evaluate(j)
needs it. It can be computed as the maximum of w[i]
over all nodes n[i]
from which there's a path to n[j]
. Actually, once I know that v[j] >= t[j]
,
the exact value v[j]
doesn't matter and I can stop the computation.
Unfortunately, this lazy algorithm is very inefficient, so it doesn't pay off even with increaseValue
being orders of magnitude more frequent than evaluate
.
I imagine, some "partially lazy" algorithm could be better, but that's just my intuition and I can't make any progress with it.
Is this somehow a well-known problem? Any other idea?
increaseThreshold
has to propagate? It may update t[i] but why it influences other nodes? – Retrospectevaluate(i)
longer butincreaseValue
is very fast. When you're doingevaluate(i)
you could also do kind of propagation but considering only those nodes withw[i] != v[i]
and updating v[i] simultaneously. In this scenario the second call forevaluate(i)
with the same argument will work almost instantly (with noincreaseValue
calls in between). – Retrospectevaluate
has to look at each node from which there's a path and this may be a substantial portion of the graph. When the values don't get propagated immediately, then you know nothing about what may have changed and you must inspect a lot of nodes. – Rathaw[i] != v[i]
only – Retrospectn[j]
in eval in the lazy approach? Is that something that could be optimized? – EsteresteraseincreaseThreshold
. It gets never smaller, but unlike the value, there's no relation between thresholds of connected nodes. – Ratha