routing: regularize bimodal model

If the success and fail amounts indicate that a channel doesn't obey a
bimodal distribution, we fall back to a uniform/linear success
probability model. This also helps to avoid numerical normalization
issues with the bimodal model.

This is achieved by adding a very small summand to the balance
distribution P(x) ~ exp(-x/s) + exp((x-c)/s), 1/c that helps to
regularize the probability distribution. The distribution becomes finite
for intermediate balances where the exponentials would be evaluated to
an exact zero (float) otherwise. This regularization is effective in
edge cases and leads to falling back to a uniform model should the
bimodal model fail.

This affects the normalization to be s * (-2 * exp(-c/s) + 2 + 1/s) and
the primitive function to receive an extra term x/(cs).

The previously added fuzz seed is expected to be resolved with this.
This commit is contained in:
bitromortac committed 2025-05-02 10:30:12 +02:00
1 parent fe32105b3e
commit 3819941c12
2 files changed
+40 -16

No files matched your search

+22 -2
View File
@@ -269,10 +269,30 @@ func TestSmallScale(t *testing.T) {
// An amount that's close to the success amount should have a very high
// probability.
amtCloseSuccess := successAmount + 1
_, err := estimator.probabilityFormula(
p, err := estimator.probabilityFormula(
capacity, successAmount, failAmount, amtCloseSuccess,
)
require.ErrorContains(t, err, "normalization factor is zero")
require.NoError(t, err)
require.InDelta(t, 1.0, p, defaultTolerance)
// An amount that's close to the fail amount should have a very low
// probability.
amtCloseFail := failAmount - 1
p, err = estimator.probabilityFormula(
capacity, successAmount, failAmount, amtCloseFail,
)
require.NoError(t, err)
require.InDelta(t, 0.0, p, defaultTolerance)
// In the region where the bimodal model doesn't give good forecasts, we
// fall back to a uniform model, which interpolates probabilities
// linearly.
amtLinear := successAmount + (failAmount-successAmount)*1/4
p, err = estimator.probabilityFormula(
capacity, successAmount, failAmount, amtLinear,
)
require.NoError(t, err)
require.InDelta(t, 0.75, p, defaultTolerance)
}
// TestIntegral tests certain limits of the probability distribution integral.