Skip to content

Decision Logic

Hoda Rezvanjoo edited this page Jun 1, 2026 · 1 revision

Modelling Choices and Their Rationale

This page consolidates the why behind the engine's modelling choices. For raw numerics, see Calibration-Constants.

Why linear programming, not heuristics or Bayesian/RL

  • Auditable. Every constraint has a name and a shadow price. "Why is Facebook capped?" gets a literal answer (the binding constraint min_spend_li_floor at £3,000). A heuristic can't be cross-examined.
  • Solves in milliseconds. CBC handles all 12 platforms × 4 objectives × 3 brackets × 3 scenarios in well under a second. Fast enough to put diagnostics + Monte Carlo + Plan B in the same UI session.
  • No training data needed. The tool is designed for one-shot quarterly planning, not continuous live-data optimisation. RL or Bayesian recalibration would be the wrong tool for the scope.

Why per-goal normalisation

Without it, "productivity" is in mixed units — clicks (large numbers) vs. leads (small). The LP would silently up-weight high-count goals. Per-goal normalisation makes the goal weights the actual control knob rather than an artefact of unit choice.

Why bracket-linear diminishing returns, not a smooth curve

A piecewise-linear bracket structure preserves the LP. A true concave function would require quadratic programming, which is:

  • a separate solver
  • harder to debug
  • slower
  • and buys very little — the bracket structure already prevents single-cell domination, which is the real failure mode

Brackets (25 / 35 / 40 % of budget at yields 1.0 / 0.65 / 0.35) approximate the curvature of "first £ buys best inventory, marginal £ buys worst" without being arbitrary.

Why James-Stein shrinkage

Without it, a 7-day Facebook history with a fluky strong week out-competes a 365-day Instagram history in the LP. Shrinkage pulls short histories toward the cross-platform mean — the standard remedy for the small-sample-winner failure mode in allocation problems.

Strength: α = days / (days + κ) with κ = 30. A 30-day history weights 50/50 against the prior. Long histories asymptote to their own data.

Why three labelled scenarios, not a continuous distribution

Three named scenarios (conservative / base / optimistic) match how strategists actually communicate. A full distribution would be more rigorous in some sense but harder to put in front of a non-technical decision-maker. The opt-in Monte Carlo robustness check gives the distributional view for users who want it — best of both.

Why goal-value weights override priority-frequency

Priority-frequency is a rank-based heuristic, useful when unit values are unknown. When you do know "a lead is worth £100," that's strictly more informative than "we ranked lead-gen #1 on three platforms." So value × productivity (expected ROAS) beats priority count whenever the user supplies values.

Why the confidence floor is 40, not 0

A score of 0 would suggest the recommendation is worthless. That's never true — even a low-confidence LP is more defensible than a hand-picked split. The floor of 40 says "treat with caution and require more measurement," which is the actionable interpretation.

Why stability_score = 1 − mean CV

A single number that maps cleanly to "% stable." Alternatives:

  • Fraction of stable platforms — discrete, jumps from 1.0 to 0.85 when one platform crosses the threshold. Bad UX.
  • Worst CV — single noisy platform dominates; unrepresentative.
  • Mean CV penalised by variance — too complex; the value of the metric is interpretability at a glance.

The materially-funded threshold (mean > £1) excludes platforms that got £0 in the optimum, so their "infinite CV" of noise around zero doesn't drag the stability score.

Clone this wiki locally