estimateHalfLife static method
- List<
RetentionBucket> buckets
Estimate the half-life of memory (in days) from retention data.
Uses a simple exponential decay fit: R(t) = 2^(-t/halfLife). Returns null if insufficient data.
Implementation
static double? estimateHalfLife(List<RetentionBucket> buckets) {
if (buckets.length < 2) return null;
// Weighted least-squares on log-transform: ln(R) = -(ln2/H) * t
// → slope = -ln2/H → H = -ln2/slope
var sumWT = 0.0;
var sumWLnR = 0.0;
var sumWT2 = 0.0;
var sumWTLnR = 0.0;
var sumW = 0.0;
for (final b in buckets) {
if (b.retentionRate <= 0 || b.retentionRate >= 1) continue;
final t = b.intervalDays.toDouble();
final lnR = math.log(b.retentionRate);
final w = b.totalReviews.toDouble(); // weight by sample size
sumW += w;
sumWT += w * t;
sumWLnR += w * lnR;
sumWT2 += w * t * t;
sumWTLnR += w * t * lnR;
}
if (sumW == 0) return null;
final slope =
(sumW * sumWTLnR - sumWT * sumWLnR) / (sumW * sumWT2 - sumWT * sumWT);
if (slope >= 0) return null; // retention can't increase with time
return -math.ln2 / slope;
}